Wikilivres frwikibooks https://fr.wikibooks.org/wiki/Accueil MediaWiki 1.47.0-wmf.8 first-letter Média Spécial Discussion Utilisateur Discussion utilisateur Wikilivres Discussion Wikilivres Fichier Discussion fichier MediaWiki Discussion MediaWiki Modèle Discussion modèle Aide Discussion aide Catégorie Discussion catégorie Transwiki Discussion Transwiki Wikijunior Discussion Wikijunior TimedText TimedText talk Module Discussion module Event Event talk Dictionnaire de philosophie/Finitude 0 9958 768465 753985 2026-06-24T03:17:43Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768465 wikitext text/x-wiki {{DicoPhilo|Finitude|lecture=oui}} {{Wiktionnaire|finitude}} La '''finitude''' désigne le caractère limité, borné, déterminé de l'existence humaine. Ce terme, d’introduction relativement tardive dans le vocabulaire philosophique français (il ne se généralise qu’au début du XX<sup>e</sup> siècle), condense pourtant une thématique aussi ancienne que la philosophie elle-même : celle des limites constitutives de la condition humaine.<ref>{{Ouvrage|lang=fr|prénom=André|nom=Lalande|titre=Vocabulaire technique et critique de la philosophie|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2010|pages=362}}</ref> Par ''finitude'', on n’entend pas seulement certaines limites factuelles (durée de la vie, fragilité du corps, champ restreint de nos connaissances), mais la structure même de l’être humain en tant qu’il n’est jamais coextensif à la plénitude de l’être : il est toujours situé, exposé, dépendant, en défaut par rapport à un absolu qu’il peut penser sans jamais le posséder. La finitude ne se confond ni avec la simple mortalité ni avec une insuffisance accidentelle de nos facultés. Elle désigne un mode d’être ontologique : l’homme n’est pas son propre fondement, il n’échappe ni au temps ni au corps ni à l’histoire. De l’Antiquité à la phénoménologie, en passant par la théologie, la métaphysique moderne et l’existentialisme, la finitude a servi à penser la condition humaine comme condition ''intermédiaire'' entre le néant et l’infini, entre la pure passivité des choses et l’auto-suffisance de Dieu ou de l’absolu. == Dimensions de la finitude == La finitude se déploie selon plusieurs dimensions qui s’entrecroisent et se renforcent mutuellement : temporelle, cognitive, pratique et, plus largement, historique et sociale. La dimension '''temporelle''' est la plus immédiatement manifeste : l’existence humaine est encadrée par une naissance et une mort, elle se déroule dans une durée finie et irréversible. Nous n’avons pas choisi de venir au monde, nous ne savons ni quand ni comment nous en sortirons ; entre ces deux extrémités, notre vie est faite d’un temps compté, toujours déjà entamé.<ref>{{Ouvrage|lang=fr|prénom=Martin|nom=Heidegger|titre=Être et temps|traducteur=François Vezin|lieu=Paris|éditeur=Gallimard|collection=Bibliothèque de philosophie|année=1986|pages=289-345|chapitre=§§ 46-53}}</ref> Blaise Pascal exprime avec force cette fragilité : « l’homme n’est qu’un roseau, le plus faible de la nature ; mais c’est un roseau pensant. Il ne faut pas que l’univers entier s’arme pour l’écraser : une vapeur, une goutte d’eau suffit pour le tuer ». La grandeur de l’homme tient précisément à ce que, conscient de cette fragilité extrême, il peut en faire l’objet d’une réflexion et d’un jugement sur la manière de vivre.<ref>{{Ouvrage|lang=fr|prénom=Blaise|nom=Pascal|titre=Œuvres complètes|éditeur=Seuil|collection=L'Intégrale|lieu=Paris|année=1963|pages=528|passage=Pensées, éd. Brunschvicg, fr. 347}}</ref> Les analyses contemporaines de la temporalité (chez Heidegger, mais aussi chez Husserl ou Bergson) montrent que cette finitude temporelle ne concerne pas seulement le « nombre » d’années à vivre, mais la structure même de l’expérience : nous ne vivons jamais que dans un présent tendu entre un passé irrévocable et un avenir ouvert, que nous ne maîtrisons pas. La dimension '''cognitive''' constitue un second aspect essentiel. Notre faculté de connaître est limitée par les conditions mêmes de son exercice. Nous ne connaissons que ce qui peut nous être donné dans l’expérience, selon les formes a priori de notre sensibilité (espace et temps) et les catégories de notre entendement. Nous ne saisissons jamais les choses telles qu’elles seraient « en soi », mais seulement les phénomènes tels qu’ils se donnent à nous, conditionnés par notre manière finie de percevoir et de penser.<ref>{{Ouvrage|lang=fr|prénom=Emmanuel|nom=Kant|titre=Critique de la raison pure|traducteur=Alain Renaut|éditeur=Flammarion|collection=GF|lieu=Paris|année=2006|pages=117-153|passage=« Esthétique transcendantale »}}</ref> Cette limitation n’est pas simplement un manque ou une déficience : elle dessine le champ dans lequel une connaissance objective est possible, au prix d’une renonciation à l’absolu métaphysique. Comme le souligne Kant, nous n’avons pas à « élargir » notre esprit jusqu’à l’infini, mais à reconnaître lucidement les frontières au-delà desquelles la raison bascule dans l’illusion. La dimension '''pratique''' ou '''éthique''' touche à notre pouvoir d’agir. La volonté humaine peut être dite libre, mais elle s’exerce toujours dans des situations déterminées, sous le poids d’un corps, d’une histoire, d’un monde déjà là, de la présence d’autrui. La liberté ne consiste pas à échapper à toute finitude, mais à se déterminer dans et à travers des contraintes factuelles, des résistances, des obstacles. Notre passé, nos engagements déjà pris, nos attaches affectives, les institutions et les rapports de force au sein desquels nous vivons, définissent un champ de possibles qui n’est jamais illimité.<ref>{{Ouvrage|lang=fr|prénom=Jean-Paul|nom=Sartre|titre=L'Être et le Néant. Essai d'ontologie phénoménologique|éditeur=Gallimard|collection=Bibliothèque des Idées|lieu=Paris|année=1943|pages=485-642|passage=IV<sup>e</sup> partie, chap. I, « Avoir, faire et être »}}</ref> C’est ce que la philosophie existentielle décrit sous le nom de ''facticité'' : nous sommes des libertés, mais des libertés situées. À ces trois dimensions s’ajoute enfin une dimension '''historique et sociale''', souvent sous-estimée dans les approches trop abstraites de la finitude. L’individu ne naît pas dans un « vide » neutre, mais au sein de structures économiques, politiques, culturelles qui conditionnent très concrètement ce qu’il est possible d’espérer et de faire. Les analyses matérialistes, en particulier celles inspirées de Marx, insistent sur cette finitude sociale : ce ne sont pas seulement le temps biologique et la structure de la raison qui limitent nos existences, mais aussi la manière dont le travail, les classes sociales, les formes de propriété et de domination organisent l’accès au savoir, à la santé, à la culture, à la parole publique.<ref>{{Ouvrage|lang=fr|prénom=Karl|nom=Marx|titre=Manuscrits de 1844, suivi de Fragments choisis|traducteur=Jean-Pierre Lefebvre|éditeur=GF Flammarion|lieu=Paris|année=1996|pages=129-140}}</ref> La finitude humaine se laisse ainsi déployer comme une trame complexe de limitations naturelles et de limitations historiquement produites. == Élaborations historiques du concept == === L’Antiquité : limite et perfection === La philosophie antique n’emploie pas le terme moderne de « finitude », mais elle pense l’être sous le couple de la limite (''péras'') et de l’illimité (''apeiron''). Chez [[Aristote]], la distinction entre puissance (''dunamis'') et acte (''energeia'') permet de penser le fini comme ce qui est en chemin vers son accomplissement. L’être fini est celui qui n’a pas encore actualisé toutes ses possibilités : il est marqué par l’inachèvement, mais aussi orienté vers une forme à réaliser, vers un ''telos'' qui lui donne sens.<ref>{{Ouvrage|lang=fr|prénom=Aristote|titre=Métaphysique|traducteur=Marie-Paul Duminil|traducteur2=Annick Jaulin|éditeur=Flammarion|collection=GF|lieu=Paris|année=2008|pages=287-291|passage=Livre Θ (IX), chap. 6, 1048a25-1048b36}}</ref> La finitude apparaît ici moins comme une déficience que comme la condition même d’un devenir orienté vers la perfection. Cette perspective se prolonge dans la conception aristotélicienne de Dieu comme acte pur, « pensée de la pensée », exempt de toute potentialité et, par là même, de tout devenir. L’acte pur, qui ne peut ni commencer ni cesser d’être ce qu’il est, se tient hors de la finitude qui affecte les êtres composés de puissance et d’acte, soumis à la génération et à la corruption.<ref>{{Ouvrage|lang=fr|prénom=Aristote|titre=Métaphysique|éditeur=Flammarion|collection=GF|lieu=Paris|année=2008|pages=407-408|passage=Livre Λ (XII), chap. 7, 1072b18-30}}</ref> La condition humaine se laisse alors comprendre comme condition médiane : ni pure actualité immuable, ni simple flux illimité, mais existence finie prise dans le temps, la croissance, le déclin. === La tradition théologique : finitude et création === La pensée chrétienne médiévale, héritière de la métaphysique grecque et de la Révélation biblique, articule la finitude à l’idée de création. Chez [[Augustin d'Hippone|saint Augustin]], la condition créaturelle de l’homme signifie qu’il reçoit son être d’un autre, qu’il n’est jamais son propre fondement. La finitude se manifeste ici comme ''mutabilité'' : alors que Dieu est éternel, immuable, la créature est livrée au temps, à cette « distension de l’âme » (''distentio animi'') qui la disperse entre un passé révolu, un avenir incertain et un présent fuyant.<ref>{{Ouvrage|lang=fr|prénom=Augustin|nom=Saint|titre=Confessions|traducteur=Louis de Mondadon|éditeur=Seuil|collection=Points Sagesses|lieu=Paris|année=1982|pages=275-291|passage=Livre XI, chap. 14-28}}</ref> La méditation augustinienne du temps fait apparaître la finitude comme tension intérieure plutôt que simple limitation extérieure. [[Thomas d'Aquin|Thomas d’Aquin]] approfondit cette analyse en décrivant la structure métaphysique de l’être créé : dans tout étant fini, l’essence (ce que la chose est) et l’acte d’être (''esse'') sont distincts. Cette composition essence/existence est le signe même de la finitude : seul Dieu, en qui essence et existence s’identifient sans reste, échappe à toute limite. Les créatures n’existent que par participation à l’acte d’être divin, elles sont radicalement dépendantes de leur Créateur.<ref>{{Ouvrage|lang=fr|prénom=Thomas|nom=d'Aquin|titre=Somme théologique|éditeur=Cerf|lieu=Paris|année=1984|pages=158-161|passage=I, q. 3, a. 4, « Dieu est-il composé d’essence et d’existence ? »}}</ref> La finitude apparaît ainsi comme l’envers ontologique de la dépendance créaturelle. Pour [[René Descartes]], la finitude se donne dans l’expérience du doute, de l’erreur et du défaut. Nous nous trompons parce que notre entendement est limité, incapable de saisir d’un seul coup tout ce qu’il juge. Mais la volonté humaine, elle, se présente comme illimitée : elle peut se porter sur une infinité d’objets possibles. La disproportion entre une volonté d’extension indéfinie et un entendement fini explique l’origine de nos erreurs : nous jugeons au-delà de ce que nous comprenons clairement et distinctement.<ref>{{Ouvrage|lang=fr|prénom=René|nom=Descartes|titre=Œuvres de Descartes|éditeur=Vrin|lieu=Paris|année=1996|pages=45-46|passage=''Méditations métaphysiques'', Quatrième Méditation|volume=IX-1|auteurs=Charles Adam|auteurs2=Paul Tannery}}</ref> L’homme cartésien est ainsi un être paradoxal : substance finie qui porte néanmoins en elle l’idée de l’infini, indice de sa dépendance à l’égard de Dieu. Chez [[Baruch Spinoza|Spinoza]], la finitude des choses ne résulte plus d’une chute ou d’un manque, mais de leur statut de ''modes'' de la seule substance infinie, Dieu ou la Nature. Une chose singulière est dite finie en ce qu’elle est déterminée à exister et à agir par d’autres choses, elles aussi finies, dans une chaîne causale sans début ni fin : elle ne possède jamais en elle-même le principe de son être, ni la capacité de se maintenir par elle-même.<ref>{{Ouvrage|lang=fr|prénom=Baruch|nom=Spinoza|titre=Éthique|traducteur=Bernard Pautrat|éditeur=Seuil|collection=Points Essais|lieu=Paris|année=2010|pages=53|passage=I, prop. 28}}</ref> La finitude se présente ici à la fois comme limitation horizontale (dépendance à l’égard d’autres modes) et comme dépendance verticale à l’égard de la substance. === Kant : la révolution critique de la finitude === [[Emmanuel Kant]] opère un renversement décisif : au lieu de penser la finitude comme simple défaut par rapport à un infini préalable, il en fait le point de départ irréductible de toute philosophie. L’homme n’est plus une copie affaiblie de l’être divin ; il est un être ''finiment rationnel'', dont la structure même de la connaissance est marquée par la finitude.<ref>{{Ouvrage|lang=fr|prénom=Michel|nom=Foucault|titre=Les Mots et les Choses. Une archéologie des sciences humaines|éditeur=Gallimard|collection=Bibliothèque des Sciences humaines|lieu=Paris|année=1966|pages=329-333|chapitre=« L’homme et ses doubles »}}</ref> Dans la ''Critique de la raison pure'', Kant montre que notre connaissance suppose toujours deux moments : la réceptivité de la sensibilité, par laquelle les objets nous sont donnés dans l’espace et le temps, et la spontanéité de l’entendement, qui les pense à l’aide de concepts. Nous ne produisons pas l’existence des choses par notre seule pensée ; nous ne faisons que structurer ce qui nous est donné, selon des formes et des catégories qui définissent la manière finie dont nous pouvons connaître.<ref>{{Ouvrage|lang=fr|prénom=Emmanuel|nom=Kant|titre=Critique de la raison pure|éditeur=PUF|collection=Quadrige|lieu=Paris|année=2012|pages=251-256|passage=Logique transcendantale, Analytique des principes, « Du principe suprême de tous les jugements synthétiques »}}</ref> La finitude est ici double : nous dépendons d’une intuition qui doit nous être fournie (nous ne sommes pas entendement intuitif) et notre entendement est discursif, procédant par concepts, jamais par saisie immédiate du réel absolu. Sur le plan moral, Kant relie également la finitude à la structure du devoir. Un être saint n’aurait pas à obéir à une loi : sa volonté serait spontanément conforme au bien. Pour l’homme, être fini soumis à des inclinations sensibles, la loi morale se présente sous la forme d’un impératif catégorique, d’un « tu dois » qui s’oppose à nos penchants. C’est précisément parce que nous sommes finis que nous éprouvons le devoir comme obligation, et que la moralité prend la forme d’un effort pour surmonter nos limitations sensibles.<ref>{{Ouvrage|lang=fr|prénom=Emmanuel|nom=Kant|titre=Critique de la raison pratique|traducteur=Jean-Pierre Fussler|éditeur=Flammarion|collection=GF|lieu=Paris|année=2003|pages=139-143|passage=Livre I, chap. I, § 7, « Loi fondamentale de la raison pure pratique »}}</ref> === Hegel : la médiation du fini et de l’infini === [[Georg Wilhelm Friedrich Hegel]] critique la manière traditionnelle d’opposer abstraitement le fini et l’infini. Dans la ''Science de la logique'', il montre qu’un infini qui se définirait simplement par l’exclusion du fini – comme ce qui serait « au-delà » de tous les êtres finis – ne serait qu’un « mauvais infini », lui-même limité par ce qu’il exclut.<ref>{{Ouvrage|lang=fr|prénom=Georg Wilhelm Friedrich|nom=Hegel|titre=Science de la logique|traducteur=Pierre-Jean Labarrière|traducteur2=Gwendoline Jarczyk|éditeur=Aubier|collection=Bibliothèque philosophique|lieu=Paris|année=1972|pages=152-173|volume=I|passage=Livre I, Sect. I, chap. 2, C}}</ref> Le véritable infini est celui qui intègre le fini en lui, qui le conserve et le dépasse à la fois (''Aufhebung''). Dans cette perspective, la finitude n’est plus une simple opposition à l’infini, mais un moment nécessaire de son déploiement. L’absolu hégélien ne se tient pas hors du monde fini ; il se réalise à travers l’histoire, à travers les formes finies de l’esprit (droit, morale, État, art, religion, philosophie). La finitude humaine perd ainsi le caractère dramatique qu’elle revêt chez d’autres penseurs : elle est un passage, une étape dans le processus par lequel l’Esprit absolu revient à soi en prenant conscience de lui-même dans ses productions finies. === Heidegger : finitude et existence === Avec [[Martin Heidegger]], la finitude devient le trait ontologique fondamental de l’existence humaine. Dans ''Être et temps'', il décrit le ''Dasein'' (l’être-là humain) comme un être pour lequel il y va de son être, et dont l’être est essentiellement ''être-pour-la-mort'' (''Sein-zum-Tode'').<ref>{{Ouvrage|lang=fr|prénom=Martin|nom=Heidegger|titre=Être et temps|éditeur=Gallimard|collection=Bibliothèque de philosophie|lieu=Paris|année=1986|pages=309-314|passage=§ 50, « Esquisse de l’analyse existentiale ontologique de la mort »}}</ref> La mort n’est pas seulement un événement futur, mais une possibilité toujours déjà présente : la possibilité pour le ''Dasein'' de ne plus pouvoir être. C’est la possibilité la plus propre, parce que nul ne peut mourir à ma place, la plus certaine, puisque je mourrai, mais aussi la plus indéterminée, car je ne sais ni quand ni comment. L’anticipation résolue de cette possibilité, loin de conduire au désespoir, ouvre selon Heidegger l’accès à une existence authentique : en se comprenant à partir de sa fin, le ''Dasein'' se dégage de l’anonymat du « On » (''das Man'') et assume son être propre. Dans ses travaux ultérieurs, Heidegger interprète également, à la suite de Kant, la finitude de l’intuition humaine comme le lieu où se joue la métaphysique : la manière finie dont l’homme reçoit l’être, au lieu de le produire, est ce qui rend possible la question de l’être elle-même.<ref>{{Ouvrage|lang=fr|prénom=Martin|nom=Heidegger|titre=Kant et le problème de la métaphysique|traducteur=Alphonse de Waelhens|traducteur2=Walter Biemel|éditeur=Gallimard|collection=Bibliothèque de philosophie|lieu=Paris|année=1953|pages=285-294|passage=§ 43, « La finitude en l’homme et la métaphysique du Dasein »}}</ref> === Existentialisme et phénoménologie === [[Jean-Paul Sartre]] reprend le thème heideggérien de la finitude, mais en le déployant dans une ontologie de la liberté. Le ''pour-soi'' (la conscience) se définit par un manque d’être, par une capacité à se distancer de ce qu’il est et de ce qu’il n’est pas ; cette structure de néantisation fonde la liberté, mais aussi la finitude du sujet.<ref>{{Ouvrage|lang=fr|prénom=Jean-Paul|nom=Sartre|titre=L'Être et le Néant|éditeur=Gallimard|collection=Bibliothèque des Idées|lieu=Paris|année=1943|pages=111-142|passage=Introduction, IV, « L’être du pour-soi »}}</ref> L’homme est toujours ''déjà'' engagé dans une situation qu’il n’a pas choisie : son corps, son milieu, son passé, ses attaches, autant de traits de sa ''facticité'' qui limitent concrètement ses possibles. Pourtant, cette finitude n’abolit pas la liberté : elle en est le cadre, et, d’une certaine manière, la matière. C’est dans et par cette finitude que le sujet se choisit. Sartre se sépare néanmoins de Heidegger sur le statut de la mort : il refuse d’en faire la possibilité la plus propre du sujet, y voyant plutôt l’irruption d’une pure facticité qui vient anéantir de l’extérieur le champ de mes projets, sans lui donner sens.<ref>{{Ouvrage|lang=fr|prénom=Jean-Paul|nom=Sartre|titre=L'Être et le Néant|éditeur=Gallimard|collection=Bibliothèque des Idées|lieu=Paris|année=1943|pages=615-638|passage=IV<sup>e</sup> partie, chap. I, I, « Ma mort »}}</ref> Là où Heidegger fait de l’anticipation de la mort le moteur d’une décision authentique, Sartre y voit surtout la limite opaque qui réduit à néant le système de mes projets. [[Maurice Merleau-Ponty]] propose une autre manière de penser la finitude, en insistant sur l’''incarnation''. Dans la ''Phénoménologie de la perception'', il part de la formule : « Il y a le monde ». Ce « il y a » désigne un donné originaire, une facticité du monde qui ne dépend pas de nous et que nous ne pouvons ramener à une construction de la conscience.<ref>{{Ouvrage|lang=fr|prénom=Maurice|nom=Merleau-Ponty|titre=Phénoménologie de la perception|éditeur=Gallimard|lieu=Paris|année=1945|pages=7-13|passage=Avant-propos}}</ref> La finitude se joue alors dans le rapport de notre ''corps propre'' au monde : nous ne sommes pas des consciences désincarnées, mais des corps situés, pris dans une histoire, un langage, des pratiques. Loin d’être simplement négative, cette finitude incarnée est le milieu vivant à partir duquel sens et liberté se déploient. [[Emmanuel Levinas]] déplace la réflexion sur la finitude vers l’éthique. Il ne s’agit plus d’abord de ma mort, mais de la mort d’autrui. La vulnérabilité du visage, sa nudité, sa capacité à souffrir et à mourir, manifestent la finitude de l’autre et me mettent en demeure de répondre de lui : « le visage d’autrui » me dit, silencieusement mais impérativement : « tu ne tueras point ». La finitude n’est plus seulement le trait ontologique de mon existence, mais ce qui se donne dans la relation éthique comme appel à la responsabilité illimitée pour l’autre homme.<ref>{{Ouvrage|lang=fr|prénom=Emmanuel|nom=Levinas|titre=Totalité et Infini. Essai sur l’extériorité|éditeur=Martinus Nijhoff|collection=Phaenomenologica|lieu=La Haye|année=1961|pages=168-187|passage=Section III, A, « Le visage et la sensibilité »}}</ref> [[Paul Ricœur]], enfin, propose dans ''Finitude et culpabilité'' une « philosophie de l’homme faillible ». L’homme lui apparaît comme marqué par une disproportion constitutive entre finitude et visée d’infini : finitude de la perception et infinité de la pensée, finitude du caractère et aspiration à un bonheur absolu, finitude de l’amour de soi et quête d’un bien inconditionné. La finitude n’est pas ici un simple manque, mais la condition d’une dynamique de dépassement, toujours menacée de retomber dans la faute et la culpabilité.<ref>{{Ouvrage|lang=fr|prénom=Paul|nom=Ricœur|titre=Finitude et culpabilité, I. L’homme faillible|éditeur=Aubier|collection=Philosophie de l’esprit|lieu=Paris|année=1960|pages=23-41|passage=Introduction}}</ref> == Finitude et condition humaine == La finitude ne renvoie donc pas seulement à des limitations factuelles ; elle définit la condition humaine comme condition ''intermédiaire''. Pascal décrit magistralement l’homme comme « un milieu entre rien et tout, infiniment éloigné de comprendre les extrêmes ». L’homme ne peut embrasser ni l’infiniment grand ni l’infiniment petit ; il est comme suspendu entre deux abîmes qu’il peut concevoir, mais non maîtriser.<ref>{{Ouvrage|lang=fr|prénom=Blaise|nom=Pascal|titre=Œuvres complètes|éditeur=Seuil|collection=L'Intégrale|lieu=Paris|année=1963|pages=504-507|passage=Pensées, éd. Brunschvicg, fr. 72}}</ref> Cette situation engendre un paradoxe : être fini, l’homme est pourtant capable de viser l’infini, de penser Dieu, l’univers, l’éternité. Cette disproportion entre ce qu’il est et ce qu’il peut penser nourrit à la fois sa grandeur et sa misère. « L’homme passe infiniment l’homme », écrit encore Pascal : par la pensée, il se dépasse lui-même, mais il ne cesse pas pour autant d’être livré à la maladie, à la souffrance, à la mort.<ref>{{Ouvrage|lang=fr|prénom=Blaise|nom=Pascal|titre=Œuvres complètes|éditeur=Seuil|collection=L'Intégrale|lieu=Paris|année=1963|pages=565|passage=Pensées, éd. Brunschvicg, fr. 434}}</ref> C’est dans cette tension que se joue le drame de l’existence humaine. La conscience de la finitude peut susciter des réponses contradictoires. Elle peut conduire au pessimisme le plus sombre. [[Arthur Schopenhauer]] voit dans la finitude et la souffrance la trame même de la vie : le vouloir-vivre, force aveugle et insatiable, engendre une quête sans fin de satisfactions toujours déçues. Vivre, c’est être pris dans un mouvement incessant de désirs inassouvis, que seule la négation du vouloir peut, partiellement, apaiser.<ref>{{Ouvrage|lang=fr|prénom=Arthur|nom=Schopenhauer|titre=Le Monde comme volonté et comme représentation|traducteur=Auguste Burdeau|éditeur=PUF|collection=Quadrige|lieu=Paris|année=2014|pages=395-421|passage=Livre IV, §§ 56-58}}</ref> À l’inverse, la reconnaissance de la finitude peut fonder une affirmation de la vie. [[Friedrich Nietzsche]], par la pensée de l’« éternel retour du même », invite à se demander si l’on pourrait vouloir revivre, à l’identique et à l’infini, la vie que l’on a vécue. L’''amor fati'', l’amour du destin, consiste à dire « oui » au caractère fini, tragique et joyeux à la fois de l’existence, au point de souhaiter qu’il se répète éternellement.<ref>{{Ouvrage|lang=fr|prénom=Friedrich|nom=Nietzsche|titre=Le Gai Savoir|traducteur=Patrick Wotling|éditeur=Flammarion|collection=GF|lieu=Paris|année=2000|pages=285-286|passage=§ 341, « Le poids le plus lourd »}}</ref> La finitude cesse alors d’être un motif de résignation pour devenir l’occasion d’une affirmation créatrice. On peut encore souligner que la finitude n’est pas homogène : les conditions de vie différentielles produisent des expériences très contrastées de la limite. Entre l’homme protégé par les garanties matérielles et sociales et celui qui vit dans la précarité extrême, l’exposition à la maladie, à la faim, à la violence, n’a pas la même forme. La finitude biologique est la même, mais la manière dont une société organise le travail, la propriété, l’accès aux soins et à la culture accentue ou adoucit cette finitude. D’un point de vue critique, la réflexion sur la finitude rejoint ainsi la question de la justice sociale : ce n’est pas parce que tous les humains sont mortels qu’il faudrait accepter sans examen les inégalités qui précipitent certains vers une mort précoce ou une vie mutilée. == Finitude, liberté et responsabilité == La finitude est aussi ce qui rend possible notre liberté et notre responsabilité. Un être infini, dont toutes les possibilités seraient d’emblée actualisées, n’aurait pas à choisir : rien ne serait à décider, rien ne serait à risquer. C’est parce que nous sommes finis, parce que nous ne disposons ni d’un temps illimité ni de toutes les possibilités simultanément, que chaque choix a un poids, que toute décision engage irréversiblement une portion de notre existence. Sartre souligne que la liberté n’est pas la négation de la finitude, mais son assomption. En choisissant, je me détermine, je trace une ligne parmi d’autres possibles, je laisse tomber d’innombrables possibilités non réalisées. « L’acte même de liberté est assomption et création de finitude » : en me projetant dans un certain projet, je délimite ma vie, je lui donne forme, et j’accepte de n’être pas tout.<ref>{{Ouvrage|lang=fr|prénom=Jean-Paul|nom=Sartre|titre=L'Être et le Néant|éditeur=Gallimard|collection=Bibliothèque des Idées|lieu=Paris|année=1943|pages=639|passage=IV<sup>e</sup> partie, chap. I, II, « Ma facticité »}}</ref> La mauvaise foi consisterait au contraire à refuser cette finitude, à se rêver pur possible sans attaches, ou inversement chose déterminée sans liberté, pour se décharger de la responsabilité de ce que l’on a fait de sa vie. Dans une perspective plus concrète, la finitude se traduit par la nécessité de hiérarchiser nos tâches, de sélectionner nos engagements, de renoncer à certains désirs pour en réaliser d’autres. À l’échelle collective, elle impose de penser la répartition de ressources qui ne sont pas infinies : temps de travail, richesses, énergie, attention. Là encore, la finitude n’est pas seulement une contrainte naturelle ; elle devient un terrain de conflits et de choix politiques. La question n’est pas de supprimer la finitude, mais de décider qui la supportera et sous quelle forme. == Transhumanisme et dépassement de la finitude == Les développements contemporains des biotechnologies, des neurosciences et de l’intelligence artificielle remettent la question de la finitude au premier plan. Le courant transhumaniste interprète les traits de la finitude humaine – vieillissement, maladie, mortalité, limitations cognitives – comme autant de problèmes techniques à résoudre. Il envisage l’« augmentation » de l’homme par la génétique, les implants, les interfaces homme-machine, voire l’extension indéfinie de la vie biologique ou la « sauvegarde » de la conscience sur des supports artificiels.<ref>{{Ouvrage|lang=en|prénom=Julian|nom=Huxley|titre=New Bottles for New Wine|éditeur=Chatto & Windus|lieu=London|année=1957|pages=13-17|chapitre=« Transhumanism »}}</ref> Ce projet soulève des interrogations philosophiques profondes. Une existence délivrée de la vieillesse et de la mort serait-elle encore une existence humaine, au sens où la philosophie a pensé jusqu’ici l’homme comme être mortel ? La finitude temporelle n’est-elle pas ce qui donne urgence à nos engagements, gravité à nos choix, intensité à nos attachements ? Si l’horizon de la mort disparaissait, nos décisions conserveraient-elles la même portée, nos projets la même densité, nos solidarités la même nécessité ? Les critiques du transhumanisme insistent sur le fait que la finitude n’est pas simplement un défaut localisable dans certaines fonctions, mais la structure même de notre rapport au monde, aux autres et à nous-mêmes. Un être qui ne serait plus soumis à la temporalité finie, à la vulnérabilité du corps, à l’exposition à la perte, pourrait-il encore éprouver le sens d’une promesse tenue, d’un pardon accordé, d’un deuil traversé ? En voulant abolir la finitude, ne risquons-nous pas d’abolir aussi ce qui rend possible la profondeur des expériences humaines, et de réduire l’homme à un ensemble de performances quantifiables ? Plusieurs auteurs ont souligné par ailleurs que le rêve de dépassement de la finitude se déploie dans un contexte économique et technique précis : celui d’un capitalisme tardif qui tend à transformer toute limitation en marché potentiel. La lutte contre la mort elle-même se trouve alors prise dans des logiques d’investissement, de brevets, d’accès inégal aux innovations, qui reconduisent sous une forme nouvelle les anciennes asymétries sociales.<ref>{{Ouvrage|lang=fr|prénom=Dominique|nom=Lecourt|titre=Humain, posthumain|éditeur=PUF|lieu=Paris|année=2003|pages=75-92}}</ref> == Conclusion == La finitude apparaît ainsi comme un thème philosophique central, d’une richesse inépuisable. Elle ne désigne pas seulement une série de limites négatives dont il faudrait s’affranchir, mais la structure ontologique fondamentale de l’existence humaine. C’est parce que l’homme est fini – mortel, limité dans sa connaissance, exposé à l’échec et à la faute, pris dans des conditions sociales déterminées – qu’il peut se rapporter à lui-même, au monde et à autrui de manière réflexive, et qu’il peut faire de sa vie une histoire, un récit, une œuvre. Assumer sa finitude, ce n’est ni se complaire dans la résignation, ni rêver d’une impossible sortie hors de la condition humaine. C’est reconnaître lucidement nos limites et, dans le même mouvement, affirmer la dignité de l’existence qui s’y déploie, en travaillant à transformer les formes concrètes – naturelles et surtout sociales – que prend cette finitude. Entre le refus désespéré de la limite et la fuite dans les illusions d’un dépassement technique illimité, une voie philosophique demeure ouverte : celle d’une pensée qui fait de la finitude non l’ennemie de l’homme, mais le lieu même où se joue la possibilité d’une vie authentiquement humaine et d’une transformation critique de ses conditions. == Notes et références == {{references}} == Bibliographie == * ARISTOTE, ''Métaphysique'', traduit par Marie-Paul Duminil et Annick Jaulin, Paris, Flammarion, « GF », 2008. * AUGUSTIN (Saint), ''Confessions'', traduit par Louis de Mondadon, Paris, Seuil, « Points Sagesses », 1982. * DESCARTES René, ''Méditations métaphysiques'', dans ''Œuvres de Descartes'', éd. Charles Adam et Paul Tannery, Paris, Vrin, 1996, t. IX-1. * FOUCAULT Michel, ''Les Mots et les Choses. Une archéologie des sciences humaines'', Paris, Gallimard, « Bibliothèque des Sciences humaines », 1966. * HEGEL Georg Wilhelm Friedrich, ''Science de la logique'', traduit par Pierre-Jean Labarrière et Gwendoline Jarczyk, Paris, Aubier, « Bibliothèque philosophique », 1972. * HEIDEGGER Martin, ''Être et temps'', traduit par François Vezin, Paris, Gallimard, « Bibliothèque de philosophie », 1986. * HEIDEGGER Martin, ''Kant et le problème de la métaphysique'', traduit par Alphonse de Waelhens et Walter Biemel, Paris, Gallimard, « Bibliothèque de philosophie », 1953. * HUXLEY Julian, ''New Bottles for New Wine'', London, Chatto & Windus, 1957. * KANT Emmanuel, ''Critique de la raison pure'', traduit par Alain Renaut, Paris, Flammarion, « GF », 2006. * KANT Emmanuel, ''Critique de la raison pratique'', traduit par Jean-Pierre Fussler, Paris, Flammarion, « GF », 2003. * LALANDE André, ''Vocabulaire technique et critique de la philosophie'', Paris, PUF, « Quadrige », 2010. * LECOURT Dominique, ''Humain, posthumain'', Paris, PUF, 2003. * LEVINAS Emmanuel, ''Totalité et Infini. Essai sur l'extériorité'', La Haye, Martinus Nijhoff, « Phaenomenologica », 1961. * MARX Karl, ''Manuscrits de 1844, suivi de Fragments choisis'', trad. Jean-Pierre Lefebvre, Paris, GF Flammarion, 1996. * MERLEAU-PONTY Maurice, ''Phénoménologie de la perception'', Paris, Gallimard, 1945. * NIETZSCHE Friedrich, ''Le Gai Savoir'', traduit par Patrick Wotling, Paris, Flammarion, « GF », 2000. * PASCAL Blaise, ''Pensées'', dans ''Œuvres complètes'', Paris, Seuil, « L'Intégrale », 1963. * RICŒUR Paul, ''Finitude et culpabilité'', t. I, ''L'homme faillible'', Paris, Aubier, « Philosophie de l'esprit », 1960. * SARTRE Jean-Paul, ''L'Être et le Néant. Essai d'ontologie phénoménologique'', Paris, Gallimard, « Bibliothèque des Idées », 1943. * SCHOPENHAUER Arthur, ''Le Monde comme volonté et comme représentation'', traduit par Auguste Burdeau, éd. revue par Richard Roos, Paris, PUF, « Quadrige », 2014. * SPINOZA Baruch, ''Éthique'', traduit par Bernard Pautrat, Paris, Seuil, « Points Essais », 2010. * THOMAS D'AQUIN, ''Somme théologique'', traduit par A.-M. Roguet, Paris, Cerf, 1984. == Articles connexes == * {{Page|Condition humaine}} * {{Page|Contingence}} * {{Page|Éternité}} * {{Page|Existence}} * {{Page|Infini}} * {{Page|Limite}} * {{Page|Mortalité}} * {{Page|Temporalité}} * {{Page|Transcendance}} {{autocat}} ruejxhv4legiki7uee0gdhmrhgrlz2n Dictionnaire de philosophie/Individu 0 30691 768468 753068 2026-06-24T03:18:13Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768468 wikitext text/x-wiki {{DicoPhilo|Individu|lecture=oui}} Cet article présente une analyse de la notion d'individu. On ne prétend cependant pas en donner des développements extrêmement fouillés, mais une matière suffisante pour comprendre les différents problèmes que soulève cette notion. L'article porte sur les deux points suivants : le mode d'être d'un individu et l'individu biologique. ''Remarque'' : Le lecteur doit se défaire de l'habitude de considérer le mot ''individu'' comme un mot désignant un être humain particulier. L'usage philosophique ne correspond pas à cette habitude du sens commun. == Propriétés == Quelles sont les propriétés d’un être qui permettent de dire qu’il s’agit d’un individu ? Cette question est un problème d’ontologie, c’est-à-dire qu’elle porte sur le problème de savoir ce qui est : on se demande ici ce qui est un individu.<ref>Nous suivons S. Chauvier, « Particuliers, individus et individuation », in ''L’Individu. Perspectives contemporaines.''</ref> En posant cette question, on ne demande pas ce qu’est la nature de l’individu. Une telle question concerne des concepts comme ''homme'' dont il faut définir l’essence. Or, l’essence est générale, alors que pour la notion d’individu on est amené à chercher ce qui distingue deux particuliers qui ont l’essence en commun : Platon et Socrate sont des hommes. Qu’est-ce qui fait qu’en tant que particuliers instanciant la même essence, ils ne sont pas le même homme ? La problématique se ramène à expliquer par quoi deux particuliers sont individués, autrement dit, quel est le mode d’être qui fait qu’ils sont distincts. === Indépendance === Un individu n'est pas une partie d'un autre être. Par exemple, un bras n'est pas considéré comme un individu, parce qu'il n'existe pas sans le corps dont il est le bras. Il n'est pas non plus possible de l'identifier indépendamment de l'individu auquel il appartient. === Unité === Un individu possède une certaine unité caractérisée par : # le fait qu’il peut être compté. Ce critère est insuffisant, car l’unité dépend de la réalité à laquelle on applique le nombre un : une chaussure et une paire de chaussures ne possèdent pas la même unité. # le fait qu’il ne peut être coupé sans perdre son identité (terme technique : anoméoméricité) : un chien coupé en deux ne donne pas deux chiens, et deux chiens collés ensemble n’en font pas un ; en revanche, une goutte d’eau donne deux gouttes d’eau, et deux gouttes d’eau en donnent une. La goutte d’eau a donc moins d’individualité que le chien. Ce critère s’applique particulièrement aux êtres organisés. Il est toutefois insuffisant. # il possède des frontières propres. Les frontières d’un État sont instituées et peuvent être modifiées ; de plus, une seule frontière peut séparer deux pays. Les frontières d’un corps (la peau) lui sont en revanche naturelles et internes, et il n’y a pas une frontière pour deux corps. # le fait qu’il a une identité trans-temporelle. Un individu a une durée dans le temps, durée qui ne détruit pas son identité. Cette permanence suggère une unité individuelle non-accidentelle et organisatrice. === Unicité === L'unité n'est cependant pas suffisante, car des objets peuvent être produits à l'identique, correspondre aux critères de l'unité, mais ne pas posséder de véritable individualité. #Un individu se distingue d'un autre par des différences accidentelles qu'il acquiert au cours de son existence. Ces différences sont externes, comme la position dans le temps et l'espace, ou l'usure. #Un individu se distingue d'un autre par des différences constitutives. Chaque individu biologique est ainsi différencié de tout autre par une identité génétique unique. #Certains individus possèdent en outre la propriété de créer leur propre différenciation. Ce sont les personnes, c'est-à-dire des individus doués d'une conscience de leur individualité et susceptibles de la développer par eux-mêmes. On parle alors d'individualisation plutôt que d'individuation. === Degrés d'individuation === Ces critères ne permettent pas seulement de déterminer ce qui est un individu, ils montrent aussi qu’il y a une échelle de l’individuation. S. Chauvier estime que l’individualisation en est le plus haut degré et que cette place explique l’usage du mot ''individu'' comme synonyme d’être humain, puisque cette faculté d’individualisation est attribuée à la personne. == L'individu biologique == === L'organisme comme paradigme de l'individu === Depuis Aristote,<ref>Nous suivons Th. Pradeu, « Qu’est-ce qu’un individu biologique ? », in ''L’Individu. Perspectives contemporaines''.</ref> l’organisme est utilisé comme exemple paradigmatique de l’individu biologique. Lorsqu’il prend des exemples de substance, désignant un être particulier et séparé (« ce qui à la fois ne se dit pas d’un certain sujet et n’est pas dans un sujet »), Aristote dit en effet : « ce cheval », « cet homme ». Ces exemples correspondent à l’intuition commune, qui dépend très largement de notre point de vue perceptif, et ils ont été jusqu'au XX<sup>eme</sup> siècle des exemples types pour les philosophes. === Inadéquation de l'organisme comme paradigme === Bien que ces exemples remplissent les critères exposés dans la section précédente, ils sont pourtant inadéquats. La diversité biologique y est en effet ignorée : le cheval appartient au taxon des mammifères qui appartient au sous-embranchement des vertébrés. Or les vertébrés ne forment qu’une petite partie du règne animal et ne peuvent donc prétendre aussi facilement au statut d’exemple type. [[File:Aspen (Populus tremuloides) 02.jpg|thumb|Chacun de ces [[w:Populus tremuloides|peupliers]] apparaît comme un individu. En réalité, ils ne forment tous qu'un seul organisme.]] Le règne animal, considéré dans son ensemble, ne remplit pas les critères de l’individuation de manière aussi claire que peut le faire un organisme vertébré : # la symbiose est une association très fréquente entre organismes d’espèces différentes. Cette association existe aussi chez l’homme. Les critères de l’indépendance et des frontières entre organismes sont dans ces cas peu pertinents. # certains êtres vivants, considérés par le sens commun comme des individus, sont en réalité constitués d’organismes qui ont leur propre cycle de vie, ou bien des êtres vivants distingués comme autant d’individus forment en réalité un seul organisme. # les gènes, les cellules, les espèces, les écosystèmes peuvent être tenus pour des individus au même titre que les organismes. Ni l’analyse de la notion d’individu, ni l’intuition du sens commun ne nous permettent de déterminer dans tous les cas ce qui est un individu biologique. === Qu’est ce que l’individu biologique ? === Ces exemples intuitifs ne tiennent pas non plus compte des théories scientifiques actuelles qui proposent une ontologie reposant sur d’autres principes que le sens commun, ontologie qui est, contrairement à ce dernier, théoriquement justifiée : # théorie de l’évolution : dans le cadre de cette théorie, l’individu est l’être vivant sur lequel s’exerce la sélection. Or, dans certains cas, la sélection peut s’exercer, non sur un organisme, mais sur un ensemble d’êtres vivants génétiquement identiques qui ne sont pas en compétition entre eux. # immunologie : le système immunitaire distingue les organismes tolérés par un organisme de ceux qui doivent être rejetés. Or, cette distinction entre un soi et un non-soi ne définit pas nécessairement les mêmes frontières que pour le sens commun. D’autre part, selon la thèse soutenue par Th. Pradeu, puisque le système immunitaire tolère des entités étrangères, un organisme est toujours hétérogène, c’est-à-dire constitué d’entités d’origines différentes. # toujours en immunologie, le système immunitaire prévient les compétitions aux différents niveaux inférieurs dans l’organisme. Cette fonction et la précédente permettent de justifier la thèse selon laquelle l’organisme est l’individu biologique le mieux individué. Ce que nous montre cet article, c’est qu’il y a plusieurs niveaux d’individuation biologique et que ces niveaux s’intègrent les uns dans les autres (gènes, cellules, organismes, etc.). L’organisme n’est donc que l’un des individus biologiques, même s’il est le plus individué, et c’est un individu qui se construit en interaction avec son environnement, en considérant le système immunitaire comme l’unité de cette interaction, unité soumise au processus de la sélection naturelle. Cette conception moderne, qui suggère chez les êtres vivants une plus ou moins grande individuation, a été développée par plusieurs philosophes contemporains,<ref>Gilbert Simondon, ''L'individu et sa genèse physico-biologique'', Jérôme Millon, 1995 ; Georges Chapouthier, ''L'homme, ce singe en mosaïque'', Odile Jacob, 2001</ref>. == Références == <references /> == Bibliographie == *Aristote, ''Catégories'' *Aristote, ''Métaphysique'', Z *Duns Scot, ''Le principe d’individuation'' *Leibniz, ''Monadologie'' *Tocqueville, ''De la démocratie en Amérique'', II, II, § 2, 4 et 8 *Benjamin Constant, ''Principes de politique'', § 18 *Stirner, ''L'Unique et sa propriété'' *Bergson, ''Les Deux Sources de la morale et de la religion'' *Bergson, ''L'Évolution créatrice'', § 1 *Mac Pherson, ''La Théorie politique de l'individualisme possessif'' *Simondon, Gilbert, ''L’Individuation à la lumière des notions de forme et d’information'', Paris, Million, 2005 *Strawson, G., ''Les Individus'', Paris, Le Seuil, 1973 *Ricœur Paul, ''Soi-même comme un autre'' *L. Dumont, ''Essais sur l'individualisme, Une perspective anthropologique sur l'individu moderne'' *G. Chapouthier, ''L'homme, ce singe en mosaïque'', Odile Jacob, 2001 *''L'Individu. Perspectives contemporaines'', Thomas Pradeu et Pascal Ludwig (sous la direction de), Vrin, 2008 == Ressources == *[http://thomaspradeu.com/researchrecherches-2/publications Publications de Th. Pradeu] (accessibles en ligne) {{autocat}} a4yfr8clh9bptjygqbkjuylop4eemmn MediaWiki:Histlegend 8 37532 768472 691473 2026-06-24T06:31:51Z JackPotte 5426 [[w:Wikipédia:Demande d'intervention sur un message système]] 768472 wikitext text/x-wiki <div style="border: 1px solid #aaa; text-align: center;" class="plainlinks"> '''Outils externes et statistiques :'''<br> [//stats.wikimedia.org/#/fr.wikibooks.org Auteurs du site] • [//tools.wmflabs.org/xtools-articleinfo/index.php?project=fr.wikibooks.org&article={{FULLPAGENAMEE}} Auteurs de la page] • [//vs.aka-online.de/cgi-bin/wppagehiststat.pl?lang=fr.wikibooks&page={{FULLPAGENAMEE}} Modifications de la page] • [//sigma.toolforge.org/usersearch.py?page={{FULLPAGENAMEE}}&server=frwikibooks Modifications d'un utilisateur] • [https://blame.toolforge.org/wikiblame.php?binary_search_inverse=true?user_lang=fr&lang=fr&project=wikibooks&article={{urlencode:{{FULLPAGENAME}}}} Rechercher l'auteur d’un passage] • [{{fullurl:{{FULLPAGENAME}}|action=info}}#mw-pageinfo-watchers Suivis] • [//pageviews.wmcloud.org/?pages={{FULLPAGENAMEE}}&project=fr.wikibooks.org Consultations] • [https://copyvios.toolforge.org/?lang=fr&project=wikibooks&title={{FULLPAGENAMEE}} Détection des plagiats] <!-- ************* outils spécifiques à un namespace -->{{#switch:{{NAMESPACENUMBER}}<!-- contenu -->|0=<!-- pu des utilisateurs -->|2= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- pdd des utilisateurs -->|3= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- Wikilivres: -->|4= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- pdd de Wikilivres: -->|5= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- messages système -->|8= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- modèles -->|10= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages] • [https://tools.wmflabs.org/embeddedincount/embeddedincount.py?dbname=frwikibooks&ns=10&title={{PAGENAMEE}} Nombre de transclusions]<!-- pages d'aide -->|12= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- catégories -->|14= • [//tools.wmflabs.org/catscan2/catscan2.php?wikilang=fr&wikifam=.wikibooks.org&basecat={{PAGENAMEE}}&basedeep=3&mode=cs&tagcat=&tagdeep=3&format=html&userlang=fr CatScan]<!-- annexes -->|100= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages]<!-- thésaurus -->|106= • [//fr.wikibooks.org/w/index.php?title=Sp%E9cial%3AIndex&prefix={{FULLPAGENAMEE}}/ Sous-pages] }} </div><!-- ************* légende standard --><br> <div style="border: 1px solid #aaa; text-align: center;"> '''Légende :''' ({{int:cur}}) = différence avec la version actuelle, ({{int:last}}) = différence avec la version précédente, <b>{{int:minoreditletter}}</b> = modification mineure </div> bwnvcnx8r4hwm9r2wo9n4tny2dwcmc9 Fonctionnement d'un ordinateur/Les circuits pour l'addition et la soustraction 0 65787 768419 768375 2026-06-23T15:56:28Z Mewtow 31375 /* Le demi-additionneur et l'additionneur complet */ 768419 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Le calcul de la retenue se fait avec une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le circuit de calcul de la retenue peut être remplacé par une '''porte à majorité''', mais cette possibilité n'est presque jamais utilisée, on lui préfère le circuit à trois portes logiques. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 6qr7yrgwss07d6tso19pqf4qxkq60wz 768420 768419 2026-06-23T16:01:04Z Mewtow 31375 /* Le demi-additionneur et l'additionneur complet */ 768420 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Le calcul de la retenue se fait avec une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] Si les demi-additionneurs sont fabriqués avec une porte XOR et une porte ET, voici ce que donne le circuit final. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le circuit de calcul de la retenue peut être remplacé par une '''porte à majorité''', mais cette possibilité n'est presque jamais utilisée, on lui préfère le circuit à trois portes logiques. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> rcqz4yjqc7uv4s0i9bvzanpsc3f4pmw 768421 768420 2026-06-23T16:07:39Z Mewtow 31375 /* Le demi-additionneur et l'additionneur complet */ 768421 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== |[[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le circuit de calcul de la retenue peut être remplacé par une '''porte à majorité''', mais cette possibilité n'est presque jamais utilisée, on lui préfère le circuit à trois portes logiques. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 63ak35597729u59z31kddzxdrwqse3m 768422 768421 2026-06-23T16:11:45Z Mewtow 31375 /* L'additionneur complet "naïf" */ 768422 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} Le circuit de calcul de la retenue peut être remplacé par une '''porte à majorité''', mais cette possibilité n'est presque jamais utilisée, on lui préfère le circuit à trois portes logiques. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> rcmdzngs3ota34qvtm585u72cvje16i 768423 768422 2026-06-23T16:13:39Z Mewtow 31375 /* L'additionneur complet "naïf" */ 768423 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} Mais une autre simplification se comprend quand on étudie le calcul de la retenue sortante. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. Mais cette possibilité n'est presque jamais utilisée, on lui préfère le circuit à trois portes logiques. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> jnrlbotvhatiekt6pg8bdv0x7r7phqj 768424 768423 2026-06-23T16:16:27Z Mewtow 31375 /* L'additionneur complet "naïf" */ 768424 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== L'additionneur précédent calcule la retenue sortante à partir de la retenue entrante. L'additionneur que nous allons voir fait quelque chose d'assez différent, et de potentiellement complémentaire : il calcule le 'bit de somme' à partir de la retenue sortante. En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> c6k4e8g7rnsv3lpxj9uvjhjjcdmzkae 768425 768424 2026-06-23T16:20:42Z Mewtow 31375 /* L'additionneur complet basé sur une modification de la retenue sortante */ 768425 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 7qvv9kvoglt07vp6cfwcakk989162ny 768426 768425 2026-06-23T16:21:29Z Mewtow 31375 /* L'additionneur complet basé sur une modification de la retenue sortante */ 768426 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une modification de la retenue sortante=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> if70ml7e4i172xzuhodfzfmcu96srnq 768427 768426 2026-06-23T16:22:35Z Mewtow 31375 /* L'additionneur complet basé sur une modification de la retenue sortante */ 768427 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuti s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Il est possible de simplifier un peu le circuit, ou du moins d'en fournir des implémentations alternatives. Par exemple, il est possible d'implémenter les demi-additionneurs uniquement avec des portes NOR ou NAND. Le tout permet d'économiser des portes logiques, en éliminant des redondances cachées dans la porte XOR. {| |- |[[File:Full Adder using NAND gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NAND.]] |- |[[File:Full Adder using NOR gates.svg|vignette|upright=2|Additionneur complet utilisant uniquement des portes NOR.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> cpznmquzbr9qm3nx04mu4363nfxha6p 768428 768427 2026-06-23T16:26:17Z Mewtow 31375 /* L'additionneur complet "naïf" */ 768428 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. La solution plus simple consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] ===L'additionneur complet "naïf"=== [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 3nw1q182ynruiy42a1ndmcyrjx139dt 768429 768428 2026-06-23T16:27:17Z Mewtow 31375 /* Les circuits pour additionner 2 ou 3 bits */ 768429 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet "naïf"=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> rxv0auooiu81jdq35vu9mncspycmwwa 768430 768429 2026-06-23T16:27:31Z Mewtow 31375 /* L'additionneur complet "naïf" */ 768430 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat légèrement sous-optimal. D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 3lwyfukwehgyr4q2ooh4ae5i0c8o4ls 768432 768430 2026-06-23T18:12:33Z Mewtow 31375 /* Le demi-additionneur et l'additionneur complet */ 768432 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> m0r8d1b8gy1rne6uue6uo2gp2urz8im 768433 768432 2026-06-23T18:13:48Z Mewtow 31375 /* Le demi-additionneur et l'additionneur complet */ 768433 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type avec une porte OU, on obtient l'additionneur complet suivant : {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> t4vglig8nyo4364q6d4g9bvt4gyyi2b 768434 768433 2026-06-23T18:29:45Z Mewtow 31375 /* L'additionneur complet basé sur des demi-additionneurs */ 768434 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} ===La propagation et la génération des retenues=== Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. L'explication exacte fait appel aux concepts de propagation, génération et absorption de retenue. L'explication part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 24cqkkbus1hbe76o5vcs1wao3rqkkx3 768435 768434 2026-06-23T18:35:39Z Mewtow 31375 /* La propagation et la génération des retenues */ 768435 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, imaginez que l'on ait un circuit qui nous dise sur une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Nous n'allons pas voir immédiatement comment construire un tel circuit, laissons la surprise pour plus tard. Pour le moment, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. Maintenant, voyons enfin le circuit qui détermine si la retenue est propagée ou générée. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Il est possible de remplacer le circuit en orange par un multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> a42482er6b2wxf9k8pu6ijdqia0f6il 768436 768435 2026-06-23T18:45:12Z Mewtow 31375 /* La propagation et la génération des retenues */ 768436 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:Partial Full-Adder.svg|centre|vignette|upright=1.5|Circuit d'un additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. |[[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> o8qzogmjmqx46gqr9px9n3rpvs4ykox 768437 768436 2026-06-23T18:47:12Z Mewtow 31375 /* La propagation et la génération des retenues */ 768437 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|centre|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> bokp9oy2a51ftjn33gak1r03rbcebko 768438 768437 2026-06-23T18:49:17Z Mewtow 31375 /* La propagation et la génération des retenues */ 768438 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. En effet, tout additionneur est composé d'additionneurs plus simples, capables d'additionner deux ou trois bits suivant la situation. Ceux-ci gèrent ce qui se passe sur une colonne. ===Le demi-additionneur et l'additionneur complet=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Le '''demi-additionneur''' est un circuit qui additionne deux bits. Nous l'avions vu dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Pour rappel, un demi-additionneur implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> gktdsq2gp06l7qmfcw758w71r8l1s0k 768439 768438 2026-06-23T19:25:13Z Mewtow 31375 /* Les circuits pour additionner 2 ou 3 bits */ 768439 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les détailler dans ce qui suit. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 10m9onrzgcdnj7hsu00e3lt9g9g5e54 768440 768439 2026-06-23T19:25:36Z Mewtow 31375 /* Les circuits pour additionner 2 ou 3 bits */ 768440 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== Si utiliser la table de vérité donne un circuit assez complexe, il y a une solution nettement plus simple, qui consiste à enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> hn1tutve6vz0z8iodh1jsb2cvhrttco 768441 768440 2026-06-23T19:27:34Z Mewtow 31375 /* Les circuits pour additionner 2 ou 3 bits */ 768441 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un additionneur complet simple enchaîne deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 7rzxrzk716h5lylmlvx6s7zjdgkngyo 768442 768441 2026-06-23T19:28:53Z Mewtow 31375 /* L'additionneur complet basé sur des demi-additionneurs */ 768442 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'additionneur de Ladner-Fisher, d'additionneur de Brent-Kung, d'additionneur de Kogge-Stone, etc. Voici ce que cela donne pour l''''additionneur de Brent-Kung''', sur 4 bits. Ne vous affolez pas, le circuit est assez simple à comprendre. les retenues 1, 2 et 4 sont calculées comme dit plus haut. Pour la troisième retenue, on combine les bits P et G de la seconde colonne avec ceux de la troisième. En clair : on profite d'une redondance. [[File:Additionneur de Kogge-Stone.jpg|centre|vignette|upright=2|Additionneur de Brent-Kung, 4 bits.]] L'additionneur de Brent-Kung est le plus lent de tous les additionneurs à calcul parallèle de préfixe, mais c'est celui qui utilise le moins de portes logiques. Il faut dire qu'il profite de toutes les redondances possibles. En comparaison, l'additionneur de Kogge-Stone ne profite pas de certaines redondances, et duplique donc des circuits. Mais en contrepartie, le résultat est un gain en performance. Pour des additionneurs 4 bits, la seule différence notable est pour le calcul de la troisième retenue, qui ne profite pas de la redondance avec la seconde colonne. Le tout est indiqué dans le schéma ci-dessous. Les circuits en rouge sont des demi-additionneurs, qui génèrent les signaux P et G pour chaque colonne. Les circuits en jaune combinent les bits P et G de deux groupes de colonnes. Les circuits en vert prennent les signaux P et G et calculent la retenue finale. [[File:4bitKoggeStone.pdf|centre|vignette|upright=2|4bitKoggeStone]] Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Mais le mieux que vous en jugiez vous-même, avec les exemples ci-dessous, qui montrent les deux additionneurs pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> to05za43ng6ah7szah9zlh7xo3ju2sg 768443 768442 2026-06-23T19:31:14Z Mewtow 31375 /* Les additionneurs à calcul parallèle de préfixe */ 768443 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> fqfvrig7pa0mptcbgdlz95mahcauh1y 768444 768443 2026-06-23T19:31:49Z Mewtow 31375 /* La propagation et la génération des retenues */ 768444 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit,colonne par colonne, avec un additionneur complet. Cela demande de coupler un additionneur complet avec plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, afin de passer d'un bit au suivant, d'une colonne à la suivante, à chaque cycle. Même chose pour le résultat, qui a sont propre registre à décalage. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] L'additionneur série a été utilisé sur d'anciens prototypes dans les années 50-60, et quelques ordinateurs commerciaux très rares. ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 911t1y03w3x1ypp16b5ld6m16r87ysi 768445 768444 2026-06-23T19:34:26Z Mewtow 31375 /* L'additionneur série */ 768445 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est le plus simple de tous. Il est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> jo5hhbqk1g7hdpx6e0v4hwisa516qz3 768446 768445 2026-06-23T19:34:40Z Mewtow 31375 /* L'addition non signée */ 768446 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. L'additionneur ''ripple carry'' pose l'addition comme en décimal, en additionnant les bits colonne par colonne avec une éventuelle retenue. Évidemment, on commence par les bits les plus à droite, comme en décimal. Il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres. Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notez aussi, sur le schéma précédent, la présence de l’entrée de retenue <math>\text{R}_\text{Entrée}</math> sur l'additionneur. L'additionneur le plus à droite est bien un additionneur complet, et non un demi-additionneur, ce qui fait qui l'additionneur a une entrée de retenue. Tous les additionneurs ont une entrée de retenue de ce type. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 890ktfafgw2ul5zm59bnqxvw0wabk1a 768447 768446 2026-06-23T19:36:53Z Mewtow 31375 /* L'additionneur à propagation de retenue */ 768447 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. Ilutilise un additionneur complet pour chaque colonne de l'addition. Pour gérer les retenues, il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres, chacun envoyant sa retenue à la colonne suivante. [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). Notez aussi, à droite du schéma précédent, l'entrée de retenue <math>\text{R}_\text{Entrée}</math>. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] L'avantage de cet additionneur est qu'il utilise très peu de portes logiques et est assez économe en transistors, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits assez anciens. Bien que très simple, cet additionneur est cependant peu performant. Le temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux nombres de 32 bits prendra deux fois plus de temps que l'addition de deux nombres de 16 bits. La raison est que le calcul des retenues s'effectue en série, l'une après l'autre. En effet, chaque additionneur doit attendre que la retenue de l'addition précédente soit disponible pour donner son résultat. Les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, il vaut mieux utiliser d'autres méthodes d'addition, plus rapides. Pour cela, les autres additionneurs utilisent diverses optimisations, qu'on détaillera plus bas. Mais ces optimisations demandent d'utiliser plus de circuits, quitte à gagner quelque peu en rapidité. Les processeurs 32 bits, et quelques processeurs 8/16 bits évolués, utilisaient d'autres solutions, qui donnent respectivement les additionneurs à saut de retenue, à sélection de retenue, et à anticipation de retenue. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> re3nfeivrh1j2llppth9ezen9rtuh0k 768448 768447 2026-06-23T19:39:40Z Mewtow 31375 /* L'additionneur à propagation de retenue */ 768448 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. Ilutilise un additionneur complet pour chaque colonne de l'addition. Pour gérer les retenues, il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres, chacun envoyant sa retenue à la colonne suivante. [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). Notez aussi, à droite du schéma précédent, l'entrée de retenue <math>\text{R}_\text{Entrée}</math>. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] Cet additionneur utilise très peu de portes logiques, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits, dont le budget en portes logiques était limité. Bien que très simple, cet additionneur est cependant peu performant. Son temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux opérandes de 32 bits prendra deux fois plus de temps que pour des opérandes de 16 bits. La raison est que les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, d'autres additionneurs ont été inventés. Ils utilisent des optimisations qui utilisent plus de circuits pour gagner en rapidité. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé. Mais les optimisations sont assez limitées. Les optimisations en question peuvent se classer en deux types. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde classe d'optimisation rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> pvsm1me30swggrlikobu29t5e3k4as6 768449 768448 2026-06-23T19:40:01Z Mewtow 31375 /* L'additionneur à saut de retenue */ 768449 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. Ilutilise un additionneur complet pour chaque colonne de l'addition. Pour gérer les retenues, il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres, chacun envoyant sa retenue à la colonne suivante. [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). Notez aussi, à droite du schéma précédent, l'entrée de retenue <math>\text{R}_\text{Entrée}</math>. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] Cet additionneur utilise très peu de portes logiques, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits, dont le budget en portes logiques était limité. Bien que très simple, cet additionneur est cependant peu performant. Son temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux opérandes de 32 bits prendra deux fois plus de temps que pour des opérandes de 16 bits. La raison est que les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, d'autres additionneurs ont été inventés. Ils utilisent des optimisations qui utilisent plus de circuits pour gagner en rapidité. Mais avant de voir ces optimisations, noua allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé de deux manières. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde manière rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> lgovnc64sumkr8qpf55393vbejgttf1 768450 768449 2026-06-23T19:40:57Z Mewtow 31375 /* L'additionneur à propagation de retenue */ 768450 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. Ilutilise un additionneur complet pour chaque colonne de l'addition. Pour gérer les retenues, il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres, chacun envoyant sa retenue à la colonne suivante. [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). Notez aussi, à droite du schéma précédent, l'entrée de retenue <math>\text{R}_\text{Entrée}</math>. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] Cet additionneur utilise très peu de portes logiques, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits, dont le budget en portes logiques était limité. Bien que très simple, cet additionneur est cependant peu performant. Son temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux opérandes de 32 bits prendra deux fois plus de temps que pour des opérandes de 16 bits. La raison est que les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, d'autres additionneurs ont été inventés. Ils utilisent des optimisations qui utilisent plus de circuits pour gagner en rapidité. Mais avant de voir ces optimisations, nous allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé de deux manières. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. Il faut alors modifier la manière dont les additionneurs complets calculent la retenue sortante. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours. En effet, elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80, utilisaient des additionneurs de ce type. La seconde manière rend l'addition plus rapide dans certains cas, mais n'améliore pas le pire des cas. Dans le pire des cas, la retenue doit être propagée du bit de poids faible vers le bit de poids fort, et on ne peut pas accélérer ce cas là. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans les autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. LA taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut simplement prendre la retenue entrante et la propager sur la retenue sortante. La retenue saute le bloc entier. Dans le cas contraire, on n'a pas le choix : on doit calculer la retenue sortante normalement, en faisant l'addition. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il y a un moyen très simple. Mais il demande d'utiliser des additionneurs complets de type P/G, à savoir qu'ils fournissent une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue. Tous les additionneurs complets doivent avoir leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est généré assez simplement : il vaut 1 si tous les additionneurs complets du bloc propagent la retenue précédente. C'est donc un vulgaire ET entre tous ces signaux. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ca donne pour un blmoc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> gusbh8yhd3bkfht61usykws269dv7ry 768451 768450 2026-06-23T19:45:24Z Mewtow 31375 /* L'additionneur à saut de retenue */ 768451 wikitext text/x-wiki Dans ce chapitre, nous allons voir les circuits capables de faire une addition ou une soustraction, ainsi que quelques circuits spécialisés. Précisons cependant que les fabricants de processeurs travaillent d'arrache-pied pour trouver des moyens de rendre ces circuits de calcul plus rapides et plus économes en énergie. Autant vous dire que les circuits que vous allez voir sont vraiment des circuits qui font pâle figure comparé à ce que l'on peut trouver dans un vrai processeur commercial ! ==Les circuits pour additionner 2 ou 3 bits== L'addition se fait en binaire de la même manière qu'en décimal. On additionne les chiffres/bits colonne par colonne, une éventuelle retenue est propagée à la colonne d'à côté. La soustraction fonctionne sur le même principe, sur le même modèle qu'en décimal. [[File:Binary Addition Demonstration.svg|centre|vignette|Exemple d'addition en binaire.]] En clair, additionner deux nombres demande d'additionner 2 bits et une retenue sur chaque colonne, et de propager les retenues d'une colonne à l'autre. La propagation des retenues est quelque chose de simple en apparence, mais qui est sujet à des optimisations extraordinairement nombreuses. Aussi, pour simplifier l'exposition, nous allons voir comment gérer une colonne avant de voir comment sont propagées les retenues. [[File:Full Adder Block.svg|vignette|upright=1|class=transparent|Additionneur complet.]] Si on effectue une addition en colonne, on doit additionner les deux bits sur la colonne, mais aussi additionner une éventuelle retenue. Il faut donc créer un circuit qui additionne trois bits : deux bits de données, plus une retenue. Ce circuit qui additionne trois bits est appelé un '''additionneur complet'''. Il fournit en sortie deux bits : un bit de somme et une retenue sortante. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- ||0||0||0|| ||0||0 |- ||0||0||1|| ||0||1 |- ||0||1||0|| ||0||1 |- ||0||1||1|| ||1||0 |- ||1||0||0|| ||0||1 |- ||1||0||1|| ||1||0 |- ||1||1||0|| ||1||0 |- ||1||1||1|| ||1||1 |} Il est possible d'utiliser un tableau de Karnaugh pour traduire la table de vérité, mais elle donne un résultat assez compliqué. La retenue et le bit de somme sont calculés à part. La retenue est calculée avec trois portes ET et une porte OU. Le bit de somme est calculé lui avec 4 portes ET, une porte OU, et trois portes NON. [[File:Full Adler with 3 entries.png|centre|vignette|upright=2|Additionneur complet, fabriqué à partir de la table de vérité.]] D'autres méthodes donnent des résultats plus compréhensibles. Nous allons les voir dans la suite de cette section. ===L'additionneur complet basé sur des demi-additionneurs=== [[File:1-bit half-adder.svg|class=transparent|vignette|Demi-addtionneur.]] Nous avons déjà vu comment additionner deux bits dans le chapitre sur les incrémenteurs, mais quelques rappels ne seront pas de trop. Le '''demi-additionneur''' est un circuit qui additionne deux bits. Il implémente la table d'addition, qui est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Mais un demi-additionneur n'additionne que deux bits, il manque de quoi additionner la retenue. Une solution pour cela est d'enchaîner deux demi-additionneurs : un qui additionne les deux bits de données, et un second qui additionne la retenue au résultat du précédent. La retenue finale se calcule en combinant les sorties de retenue des deux demi-additionneurs, avec une porte OU. Le résultat est un additionneur complet fabriqué avec deux demi-additionneurs. Pour vous en convaincre, établissez la table de vérité de ce circuit, vous verrez que ça marche. [[File:Full Adder Blocks.svg|centre|vignette|upright=2|Additionneur complet fabriqué avec deux demi-additionneurs.]] [[File:Half-adder.svg|vignette|upright=1|Circuit d'un demi-additionneur naïf.]] L'implémentation naïve d'un demi-additionneur utilise une porte XOR et une porte ET, comme illustré ci-contre. Le circuit s'obtient en faisant uen traduction littérale de la table de vérité du circuit. Si je dis qu'elle est naïve, c'est car il est possible de l'optimiser, de manière à éliminer des redondances cachées. Mais nous avions déjà vu cela dans le chapitre sur les incrémenteurs, aussi laissons cela pour plus tard. En combinant deux demi-additionneurs de ce type, on obtient l'additionneur complet suivant. Les deux sorties de retenue des demi-additionneurs sont combinées avec une porte OU, pour calculer la retenue finale. {| class="flexible" |[[File:Full Adder Modules.svg|class=transparent|Composition d'un additionneur complet. On voit bien que celui-ci est composé de deux demi-additionneurs, en rouge et en bleu, auxquels on a ajouté une porte OU pour calculer la retenue finale.]] |[[File:Full-adder.svg|300px|class=transparent|Circuit d'un additionneur complet.]] |} Le fait de combiner les deux retenues avec une porte OU n'est pas ce qu'il y a de plus intuitif. La table de vérité nous dit que ça fonctionne, mais on comprend mal pourquoi. Mais tout devient plus clair quand on sait que les deux retenues ne peuvent pas être à 1 en même temps. Même dans l'addition 1 + 1 + 1, seule une retenue est à 1. Soit l'addition des deux bits d'opérande donne naissance à une retenue, soit c'est l'addition ''résultat + retenue entrante''. La retenue sortant est donc à 1 quand une des deux addition donne une retenue. D'où l'usage d'une porte OU. Remarquez qu'une porte XOR donne le même résultat, vu que le cas où les deux retenues sont à 1 n'est jamais rencontré. ===La propagation et la génération des retenues=== L'additionneur complet que nous allons voir dans cette section sert à introduire les concepts de propagation, génération et absorption de retenue. Il s'agit de concepts très importants quand on étudie les additionneurs. l'idée part d'un principe très simple : la retenue sortante dépend de la retenue d'entrée. La relation entre les deux se résume à trois cas, qui dépendent de la valeur des deux bits additionnés, nommés A et B. * Dans le premier cas, la retenue entrante est égale à la retenue sortante. On dit que la retenue entrante est propagée par l'additionneur. * Dans le second cas, la retenue est forcée à 0 : la retenue sortante vaut 0, peu importe la valeur de la retenue entrante. * Dans le troisième cas, la retenue est forcée à 1 : la retenue entrante vaut 1, peu importe la valeur de la retenue entrante. [[File:Signaux P et G fournis par un demi-additionneur.png|vignette|Signaux P et G fournis par un demi-additionneur]] Maintenant, créons un circuit qui nous dise si une retenue est propagée ou générée. Il a deux bits de sortie, nommés P et G : P pour ''Propagate'', G pour ''Generate''. Le bit P est à 1 si la retenue entrante est propagée, il est à 0 sinon. Le bit G est à 1 si une retenue est générée, à 0 sinon. Une retenue est considérée comme absorbée si elle n'est pas ni propagée ni générée, pas besoin d'un troisième bit pour gérer ce cas. Il se trouve que ce circuit n'est autre qu'un demi-additionneur ! Pour vous en rendre compte, regardez la table de vérité d'un additionneur complet, illustrée ci-dessous. Lorsque les deux bits d'opérande sont à 0, la retenue sortante vaut toujours 0. Si ils sont tous deux à 1, alors la retenue sortante vaut 1. S'ils sont différents, alors retenues sortante et entrante sont égales. Le bit P est donc généré par une simple porte XOR. Quant au bit G, il est à 1 si les deux bits d'opérandes sont à 1, ce qui correspond à une porte ET. Il se trouve que ces deux portes forment un demi-additionneur ! {|class="wikitable" |- ! Opérande 1 !! Opérande 2 !! Retenue entrante !! !! Retenue sortante |- class="f_rouge" ||0||0||0|| ||0 |- class="f_rouge" ||0||0||1|| ||0 |- class="f_bleu" ||0||1||0|| ||0 |- class="f_bleu" ||0||1||1|| ||1 |- class="f_bleu" ||1||0||0|| ||0 |- class="f_bleu" ||1||0||1|| ||1 |- class="f_vert" ||1||1||0|| ||1 |- class="f_vert" ||1||1||1|| ||1 |} Ensuite, créons un circuit qui prend ces deux sorties P et G, et calcule la retenue sortante en fonction. Le circuit en question a trois entrées : la retenue entrante, les deux bits P et G. La retenue sortante vaut 1 soit si une retenue est générée, soit si la retenue entrante est propagée et qu'elle vaut 1. En notant <math>{C_{in}}</math> et <math>{C_{out}}</math> les retenues entrantes et sortante, on a : : <math>{C_{out}} = G + \left( P . C_{in} \right)</math> Le circuit est donc composé d'une porte OU et d'une porte ET. En combinant un demi-additionneur avec le circuit de calcul de retenue sortante vu plus haut, on a : [[File:Additionneur complet avec propagation et génération de retenue.png|class=transparent|centre|vignette|upright=2|Additionneur complet avec propagation et génération de retenue.]] Certes, on retombe sur le circuit vu plus haut. Mais il est possible de remplacer le circuit en orange par un autre. Par exemple, il est possible de le remplacer par multiplexeur, qui choisit entre la retenue générée et la retenue entrante (propagée). Le choix se fait selon la valeur du bit P, qui chosiit entre propager la retenue et la générer. [[File:Additionneur crée avec un multiplexeur.png|centre|vignette|upright=2|Additionneur crée avec un multiplexeur]] Le circuit exact est illustré ci-dessous. Il semble utiliser plus de portes logiques que l'additionneur complet précédent. Cependant, nous verrons dans quelques chapitres qu'il est possible d'implémenter un multiplexeur avec seulement 6 transistors, voire moins ! L'implémentation utilise des portes à transmission, mais nous en reparlerons dans le chapitre sur les transistors, quand nous verrons les additionneurs à ''Manchester Carry Chain''. Au passage, une variante de ce circuit a été utilisée dans le processeur processeur 8086 d'Intel, comme on le verra dans le chapitre suivant. [[File:Additionneur complet basé sur un MUX.png|centre|vignette|upright=2|Additionneur complet basé sur un MUX]] [[File:FulladderPG.png|vignette|upright=2|Additionneur complet avec deux sorties P et G.]] Pour finir, sachez qu'il existe des additionneurs qui fournissent : le bit de résultat, deux sorties P et G qui indiquent si l'addition propage ou génère une retenue. Il ne s'agit pas d'additionneurs complets, car il manque de quoi calculer la retenue sortante. De tels additionneurs seront appelés des '''additionneurs partiels'''. De tels additionneurs sont utilisés dans certains additionneurs pour gagner en performance. Enfin, il existe aussi ce que j'ai décidé d'appeler des '''additionneurs P/G''', qui sont des additionneurs complets auxquels on a ajouté deux sorties P et G, en plus de la sortie de retenue. Leur circuit est le même que celui d'un additionneur complet, auquel on a ajouté deux fils. Vu que ces deux sorties sont fournies par le premier demi-additionneur, ajouter ces deux sorties demande d'ajouter des fils, pas de portes logiques. De tels additionneurs sont aussi utilisés dans certains additionneurs pour gagner en performance. ===L'additionneur complet basé sur une porte à majorité=== Maintenant, voyons une dernière implémentation possible de l'additionneur complet. Mais avant de voir comment l'additionneur est implémenté, nous allons devoir faire un petit focus sur la retenue sortante. Reprenons la table de vérité, et regardons ce qu'il en est pour la retenue sortante uniquement. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante |- ||0||0||0|| ||0 |- ||0||0||1|| ||0 |- ||0||1||0|| ||0 |- ||0||1||1|| ||1 |- ||1||0||0|| ||0 |- ||1||0||1|| ||1 |- ||1||1||0|| ||1 |- ||1||1||1|| ||1 |} Vous remarquerez que la retenue sortante est égale au bit majoritaire, parmi les trois bits d'opérande. Si deux ou trois bits sont à 1, la retenue sortante vaut 1. Et réciproquement avec 0. Le circuit de calcul de la retenue peut donc être remplacé par une '''porte à majorité'''. [[File:Additionneur crée avec une porte à majorité.png|centre|vignette|upright=2|Additionneur crée avec une porte à majorité]] Mais une porte à majorité est assez gourmande en circuit, ce qui fait qu'un additionneur pareil ne serait pas pratique, ni utile. Du moins, ce serait le cas s'il n'y avait pas une possibilité d'optimisation extrêmement intéressante. Il est possible de calculer le 'bit de somme' à partir de la retenue sortante ! En effet, le bit de somme est l'inverse de la retenue sortante, sauf dans deux cas : les trois bits d'entrée sont à 0, où ils sont tous à 1. Le bit de somme vaut 0 dans le premier cas, 1 dans le second cas. {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! Opérande 2 !! !! Retenue sortante !! Bit de somme |- class="f_bleu" ||0||0||0|| ||0||0 |- class="f_vert" ||0||0||1|| ||0||1 |- class="f_vert" ||0||1||0|| ||0||1 |- class="f_vert" ||0||1||1|| ||1||0 |- class="f_vert" ||1||0||0|| ||0||1 |- class="f_vert" ||1||0||1|| ||1||0 |- class="f_vert" ||1||1||0|| ||1||0 |- class="f_rouge" ||1||1||1|| ||1||1 |} En clair, 6 lignes de la table de vérité sur 8 peuvent se calculer avec une porte à majorité, le reste demandant quelques portes logiques pour faire la correction. L'implémentation en circuit demande donc trois choses : * de calculer la retenue sortante et de quoi l'inverser ; * un circuit qui vérifie si tous les bits opérande valent 0 : une porte NOR ou OU fait l'affaire ; * un circuit qui vérifie s'ils valent tous 1, à savoir une porte ET. Ensuite, on combine le résultat des trois circuits précédents pour obtenir le résultat final. La combinaison est le fait du circuit en jaune dans le schéma ci-dessous. [[File:Full adder basé sur une modification de la retenue.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue]] Le circuit en jaune est assez simple. Quand la porte ET sort un 1, la sortie doit être forcée à 1. Par contre, quand la porte OU sort un zéro, la sortie doit être forcée à 0. Il suffit donc d'enchainer un circuit de mise à 1 et un circuit de mise à 0. Nous avons vu dans le chapitre sur les opérations de masquage qu'il s'agit respectivement d'une porte OU et d'une porte ET. [[File:Full adder basé sur une modification de la retenue interne, au complet.png|centre|vignette|upright=2|Full adder basé sur une modification de la retenue interne, au complet]] Divers processeurs utilisaient des additionneurs complets de ce type : le fameux Z80, l'Intel 4004 et de l'Intel 8008 sont les exemples les plus notables. Pourtant, on pourrait s'étonner qu'un tel circuit ait existé. Il utilise beaucoup de portes logiques, a une profondeur logique supérieure : il n'a rien d'avantageux. Sauf qu'il était utilisé sur d'anciens processeurs, qui utilisaient la technologie dite TTL, différente de la technologie CMOS des transistors modernes. Et avec la technologie TTL, il est possible de fusionner plusieurs portes logiques ET et NOR en une seule porte logique ET/OU/NON ! Un additionneur complet construit ainsi ne prenait que deux portes logiques : une pour le calcul de la retenue sortante, une autre pour le reste du circuit. ==L'addition non signée== Voyons maintenant un circuit capable d'additionner deux nombres entiers: l''''additionneur'''. Dans la version qu'on va voir, ce circuit manipulera des nombres strictement positifs. L'addition des nombres codés en complètement à deux sera vu dans une section ultérieure. ===L'additionneur série=== Il est possible d'additionner deux nombres bit par bit, gr$ace à un additionneur complet associé à plusieurs registres à décalages. Les opérandes sont placées chacune dans un registre à décalage, et l'additionneur complet utilise les bits sortants de ces registres à décalage. Le bit du résultat est envoyé au registre à décalage pour le résultat. La retenue de l'addition est stockée dans une bascule de 1 bit, en attente du prochain cycle d'horloge. Un tel additionneur est appelé un '''additionneur série'''. Il a été utilisé sur d'anciens ordinateurs dans les années 50-60, aussi bien des prototypes que des ordinateurs commerciaux. [[File:Additionneur série.jpg|centre|vignette|upright=2.5|Additionneur série.]] ===L'additionneur à propagation de retenue=== L''''additionneur à propagation de retenue''' est aussi appelé l'additionneur ''ripple carry'', c'est son nom anglais. J'utiliserais occasionnellement le nom anglais dans ce qui suit, car celui-ci est plus court. Ilutilise un additionneur complet pour chaque colonne de l'addition. Pour gérer les retenues, il suffit ainsi de câbler des additionneurs complets les uns à la suite des autres, chacun envoyant sa retenue à la colonne suivante. [[File:Ripplecarryadder.png|centre|vignette|upright=2.5|Additionneur à propagation de retenue.]] Notons la présence de la retenue sortante, qui est utilisée pour détecter les débordements d'entier, ainsi que pour d'autres opérations. Le bit de retenue final est souvent stocké dans un registre spécial du processeur (généralement appelé ''carry flag''). Notez aussi, à droite du schéma précédent, l'entrée de retenue <math>\text{R}_\text{Entrée}</math>. Elle est très utile pour l'implémentation de certaines opérations comme l'inversion de signe, la soustraction, l'incrémentation, etc. Certains processeurs sont capables de faire une opération appelée ADC, ADDC ou autre nom signifiant ''Addition with Carry'', qui permet de faire le calcul A + B + Retenue (la retenue en question est la retenue sortante de l'addition précédente, stockée dans le registre ''carry flag''). Son utilité principale est de permettre des additions d'entiers plus grands que ceux supportés par le processeur. Par exemple, cela permet de faire des additions d'entiers 32 bits sur un processeur 16 bits. [[File:Adder Network 3 Bit Sum Delay 003.svg|vignette|upright=0.5|Propagation de retenue dans l'additionneur.]] Cet additionneur utilise très peu de portes logiques, ce qui fait qu'il était utilisé sur certains processeurs 8 et 16 bits, dont le budget en portes logiques était limité. Bien que très simple, cet additionneur est cependant peu performant. Son temps de calcul est proportionnel à la taille des opérandes. Par exemple, additionner deux opérandes de 32 bits prendra deux fois plus de temps que pour des opérandes de 16 bits. La raison est que les retenues doivent se propager à travers le circuit, du premier additionneur jusqu'au dernier. L'addition étant une opération fréquente, d'autres additionneurs ont été inventés. Ils utilisent des optimisations qui utilisent plus de circuits pour gagner en rapidité. Mais avant de voir ces optimisations, nous allons voir s'il est possible d'optimiser les additionneurs à propagation de retenue. ===L'additionneur à saut de retenue=== L'additionneur à propagation de retenue peut être optimisé de deux manières. La première accélère la propagation de la retenue, en agissant au niveau des additionneurs complets. La ''Manchester carry chain'' est une optimisation de ce type, mais on ne peut pas encore expliquer à ce stade du cours, car elle optimisait les additionneurs complets au niveau des transistors eux-mêmes. Elle a été utilisée sur de nombreux processeurs connus, comme le 8086 d'Intel ou le Z80. La seconde manière rend l'addition plus rapide dans certains cas. Le résultat est un additionneur dont le temps de calcul est variable. Le calcul prendra quelques cycles d'horloges avec certains opérandes, mais d'autres opérandes ne verront aucune amélioration. Il n'améliore pas le pire des cas, dans lequel la retenue doit être propagée du début à la fin, du bit de poids faible au bit de poids fort. Mais dans d'autres cas, il permet d'avoir le résultat en avance. L'optimisation en question donne l''''additionneur à saut de retenue''' (''carry-skip adder''). Il est composé de blocs qui additionnent 4/5 bits, rarement plus. La taille d'un bloc varie d'un additionneur à l'autre, elle peut même varier dans l'additionneur, mais nous allons prendre un exemple où les blocs font 4 bits. L'idée est de détecter précocement si la retenue entrante est propagée à travers tout le bloc. Si la retenue est propagée dans tous le bloc, on peut directement l'envoyer sur la sortie de retenue, la retenue saute le bloc entier. Dans le cas contraire, on doit calculer la retenue normalement. Le choix entre les deux est le fait d'un multiplexeur. Toute la difficulté est de savoir comment commander le multiplexeur. [[File:Carry skip adder, principe de base.png|centre|vignette|upright=2.5|Carry skip adder : principe de base]] Pour savoir si une retenue est propagée dans un bloc entier, il faut utiliser des additionneurs complets, qui ont en plus une sortie P indiquant que l'additionneur propage la retenue. Le bloc propage une retenue si chaque additionneur complet propage la retenue, donc s'ils ont tous leur sortie P à 1. Un simple ET logique suffit à déterminer si c'est le cas. Le signal de commande du multiplexeur est donc un vulgaire ET entre toutes les sorties P des additionneurs complets du bloc. [[File:Additionneur à saut de retenue.png|centre|vignette|upright=2.5|Calcul de la commande du MUX.]] Voici ce que ça donne pour un bloc de 4 bits : [[File:CSAdder4Bit.svg|centre|vignette|upright=1.5|Additionneur ''carry skip'' : bloc de 4 bits.]] L'additionneur à saut de retenue est construit en assemblant plusieurs blocs de ce type. [[File:BCSAdder16Bit.svg|centre|vignette|upright=3|Additionneur à saut de retenue.]] ===L'additionneur à sélection de retenue=== L''''additionneur à sélection de retenue''' utilise aussi des blocs, comme les additionneurs précédents. L'addition se fait en deux versions : une avec la retenue du bloc précédent valant zéro, et une autre version avec la retenue du bloc précédent valant 1. Il suffira alors de choisir le bon résultat avec un multiplexeur, une fois cette retenue connue. On gagne ainsi du temps en calculant à l'avance les valeurs de certains bits du résultat, sans connaître la valeur de la retenue. Petit détail : sur certains additionneurs à sélection de retenue, les blocs de base n'ont pas la même taille. Cela permet de tenir compte des temps de propagation des retenues entre les blocs. [[File:Additionneur à sélection de retenue.png|centre|vignette|upright=1.5|Additionneur à sélection de retenue avec seulement deux blocs.]] Dans les exemples du dessus, chaque sous-additionneur étaient des additionneurs à propagation de retenue. Mais ce n'est pas une obligation, et tout autre type d’additionneur peut être utilisé. Par exemple, on peut faire en sorte que les sous-additionneurs soient eux-mêmes des additionneurs à sélection de retenue, et poursuivre ainsi de suite, récursivement. On obtient alors un '''additionneur à somme conditionnelle''', plus rapide que l'additionneur à sélection de retenue, mais qui utilise beaucoup plus de portes logiques. ===Les additionneurs à anticipation de retenue=== Les '''additionneurs à anticipation de retenue''' calculent chaque retenue sans avoir à propager les retenues précédentes. Au lieu de calculer les retenues une par une, ils calculent toutes les retenues en parallèle, à partir des bits des opérandes. Une fois les retenues pré-calculées, il suffit de les additionner avec les deux bits adéquats, pour obtenir le résultat. Ces additionneurs sont composés de deux parties : * un circuit qui pré-calcule les retenues, sans les propager, directement à partir des opérandes ; * d'une couche d'additionneurs complets, qui additionnent chacun deux bits d'opérande et la retenue pré-calculée. [[File:Additionneur à anticipation de retenue.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue.]] Le calcul des retenues se fait en deux étapes. La première détermine si les retenues sont propagées ou générées, pour chaque colonne. Elle détermine, pour chaque colonne, les bits P et G qui indiquent respectivement : qu'une retenue a été générée sur cette colonne, que la colonne propage la retenue précédente. La seconde étape utilise ces signaux P et G pour déterminer la retenue sur chaque colonne. Le circuit de calcul des retenues est donc composé de deux parties : une couche de demi-additionneurs pour générer les signaux P et G, un circuit de calcul des retenues proprement dit. [[File:Circuit complet d'un additionneur à anticipation de retenue.png|centre|vignette|upright=2|Circuit complet d'un additionneur à anticipation de retenue.]] Pour rappel, la retenue de la colonne i, notée <math>C_i</math> est égale à : : <math>G_i + (P_i . C_{i-1})</math>, avec G le signal de génération de retenue, P le signal de propagation de retenue. Si on utilisait cette formule sans trop réfléchir, on retomberait sur un additionneur à propagation de retenue inutilement compliqué. L'astuce des additionneurs à anticipation de retenue consiste à remplacer le terme Ci−1 par sa valeur calculée avant. Par exemple, je prends un additionneur 4 bits. Je dispose de deux nombres A et B, contenant chacun 4 bits : A3, A2, A1, et A0 pour le nombre A, et B3, B2, B1, et B0 pour le nombre B. Si j'effectue les remplacements, j'obtiens les formules suivantes : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Ces formules nous permettent de déduire la valeur d'une retenue directement : il reste alors à créer un circuit qui implémente ces formules, et le tour est joué. [[File:Four bit adder with carry lookahead.svg|centre|vignette|upright=1.5|Additionneur à anticipation de retenue de 4 bits.]] Plus haut, j'ai dit que le circuit était composé de trois couches : une couche de demi-additionneur pour les signaux P et G ; un circuit d'anticipation de retenue, puis l'addition finale. Mais les deux bits d'opérandes sont déjà additionnés dans la couche de demi-additionneur, autant réutiliser le résultat pour l'additionner à la retenue. Pour éliminer toute redondance de ce type, il est possible d'utiliser des additionneurs partiels (des additionneurs où la sortie de retenue a été remplacée par deux sorties P et G). L'additionneur final est alors composé de plusieurs additionneurs complets de ce type, couplé à un circuit d'anticipation de retenue. [[File:Cla4bits.png|centre|vignette|upright=2.5|Additionneur à anticipation de retenue de 4 bits.]] Les additionneurs à anticipation de retenue sont plus rapides que les additionneurs à propagation de retenue. La raison est que les retenues sont calculées rapidement, dans un temps plus petit qu'en propageant la retenue. Pour rentrer dans les détails mathématiques, le temps de calcul n'est pas proportionnel au nombre de bits, mais proportionnel au logarithme de ce nombre de bits. Par contre, le gain en temps de calcul s'accompagne d'un cout en prote logique conséquent. Le circuit qui calcule les retenues anticipées utilise beaucoup de portes logiques. La conséquence est qu'utiliser un additionneur à anticipation de retenue est une solution pratique pour additionner 4 ou 8 bits. Mais pour des opérandes plus grandes, de 16 ou 32 bits, cela utiliserait trop de portes logiques. Une partie de ce cout en portes logiques est cependant lié à des redondances. Si on analyse deux retenues différentes, à des colonnes différentes. Les circuits qui calculent ces deux retenues seront différents, mais ils contiendront des sous-circuits identiques. Pour vous en rendre compte, reprenons les quatre équations obtenues précédemment et essayez de trouver des redondances : * C1 = G0 + ( P0 · C0 ) ; * C2 = G1 + ( P1 · G0 ) + ( P1 · P0 · C0 ) ; * C3 = G2 + ( P2 · G1 ) + ( P2 · P1 · G0 ) + ( P2 · P1 · P0 · C0 ) ; * C4 = G3 + ( P3 · G2 ) + ( P3 · P2 · G1 ) + ( P3 · P2 · P1 · G0 ) + ( P3 · P2 · P1 · P0 · C0 ). Vous devriez trouver : * le terme ''P0 · C0'' dans toutes les lignes ; * les termes ''P1 · P0 · C0'' et ''P1 · P0'' dans les trois dernières lignes ; * le terme ''P2 · P1 · P0 · C0'' ; ''P2 · P1 · G0'' et ''P2 · G1'' dans les deux dernières lignes. ===Les additionneurs à calcul parallèle de préfixe=== Il existe plusieurs manières d'exploiter de telles redondances, exploitées dans les '''additionneurs à calcul parallèle de préfixe'''. L'optimisation apportée est de générer des signaux ''propagate'' et ''generate'' pour des groupes de 2, 3, 4, ..., N colonnes. Par exemple, il est possible de générer un signal ''P 0 vers 3'', qui indique si la retenue de la première colonne est propagée jusqu'à la 4ème colonne. Un autre exemple est un signal qui indique qu'une retenue a été générée entre les colonnes 4 à 7 génèrent une retenue ou non. En clair, les signaux P et G ont maintenant un intervalle, qui précise de quelle colonne vers quelle colonne se fait la propagation, ou entre quelles colonnes se fait la génération. Il est possible de combiner les signaux P et G de deux groupes de colonne, s'ils sont contiguës (ils peuvent aussi se recouvrir). Par exemple, il est possible de calculer les bits P et G pour les colonnes 0 à 10, à partir des deux signaux P/G des colonnes 0-4 et 5-10. Pour cela, les équations sont assez simples. Si je prends deux groupes nommés A et B, avec A pour les colonnes de poids fort et B celles de poids faible, on a : : <math>P_{sortie} = P_A . P_B</math> : <math>G_{sortie} = G_A . P_A . G_B</math> Pour les bits des colonnes 2, 4, 8, 16, 32, 64, et autres, le calcul est simple. L'idée est de grouper les colonnes par groupes de 2. Puis, on calcule chaque groupe de 4 bits à partir de deux groupes de 2. Puis les groupes de 8 bits sont calculés à partir de deux groupes de 4 bits, et ainsi de suite pour toute puissance de deux. [[File:Squelette d'un additionneur à calcul parallèle de préfixe.jpg|centre|vignette|upright=2|Squelette d'un additionneur à calcul parallèle de préfixe]] Les seules difficultés surviennent pour les colonnes dont le nombre n'est pas une puissance de deux. Il y a plusieurs manières pour subdiviser ces colonnes en intervalles plus petits et combiner le tout. Et elles donnent chacune des additionneurs différents. Ils portent les noms d'''additionneur de Ladner-Fisher'', d'''additionneur de Brent-Kung'', d'''additionneur de Kogge-Stone'', etc. Dans le cas général, l'additionneur de Kogge-Stone est un des plus rapide, mais aussi un des plus gourmand en circuits, alors que c'est l'inverse pour l'additionneur de Brent-Kung. Les deux additionneurs sont illustrés ci-dessous, pour des opérandes de 8 bits. Dans ceux-ci, chaque losange calculent les bits P et G, à partir des signaux P et G de deux groupes précédents. {| |[[File:Brent-kung-8-bit.png|vignette|Brent-kung-8-bit]] |[[File:Kogge-stone-8-bit.png|vignette|upright=1.2|Kogge-stone-8-bit]] |} ===Les additionneurs avec anticipation de retenue entre plusieurs additionneurs=== Dans cette section, nous allons voir des additionneurs conçus en assemblant des additionneurs à plus simples, qui additionnent environ 4 à 5 bits, parfois plus, parfois moins. Ces additionneurs simples seront nommés ''blocs'' dans ce qui suit, et l'un d'entre eux est illustré ci-contre. Chaque bloc prend en entrée un morceau des deux opérandes à additionner, mais aussi une retenue d'entrée. Les blocs sont tous identiques dans le cas le plus simple, mais il est possible d'utiliser des blocs de taille variable. Par exemple, le premier bloc peut avoir des opérandes de 6 bits, le second des opérandes de 7 bits, etc. Faire ainsi permet de gagner un petit peu en performances, si la taille de chaque bloc est bien choisie. La raison est une question de temps de propagation des retenues. La retenue met plus de temps à se propager à travers 8 blocs qu'à travers 4, ce qui prend plus de temps qu'à travers 2 blocs, etc. En tenir compte fait que la taille des blocs tend à augmenter ou diminuer quand on se rapproche des bits de poids fort. ====Le calcul parallèle de la retenue==== [[File:Full-adder-4bits-serial-CEI.svg|vignette|upright=0.5|Additionneur 4 bits, un bloc.]] Plus haut, nous avons vu l'anticipation de retenue. Il est possible de l'adapter pour fonctionner avec des blocs. Une première idée est d'utiliser plusieurs additionneurs à anticipation de retenue, chacun étant un bloc. Vu qu'il s'agit d'additionneurs, ils disposent d'une sortie de retenue pour la retenue sortante, et d'une entrée de retenue pour la retenue entrante. Par exemple, le schéma ci-contre illustre un additionneur 4 bits de ce type. De ce fait, il est possible de propager les retenues d'un bloc à l'autre. par exemple, on peut utiliser 4 additionneurs à anticipation de retenue de 4 bits, et propager les retenues entre eux. Le premier bloc calcule une retenue, qui est propagée au second bloc. Le second bloc calcule lui aussi une retenue, qui est propagée au troisième bloc, etc. [[File:4008 Functional Diagram.svg|vignette|upright=1|4008 Functional Diagram]] Le gain en performance est significatif, mais il est possible de faire presque aussi rapide, tout en économisant beaucoup de circuits. L'idée est de simplifier les additionneurs 4 bits, afin de ne pas utiliser une anticipation de retenue complète. L'anticipation de retenue n'est utilisée que pour la retenue sortante, alors que les bits de somme sont calculées avec propagation de retenue. La retenue sortante est donc calculée en parallèle de l'addition. Chaque bloc contient, à côté d'un additionneur proprement dit, un circuit qui calcule la retenue sortante. Il existe de nombreuses manières de calculer la retenue sortante. Le gain en portes logiques est assez significatif. En effet, on se passe de circuits d'anticipation de retenue pour les 4 bits de somme, on ne garde que celui pour la retenue sortante. Le fait d'utiliser la propagation de retenue pour calculer les 4 bits de somme est censé avoir un léger cout en performance, mais il se trouve que ce cout est très faible. En effet, le résultat n'est connu qu'une fois les retenues propagées jusqu'au dernier bloc. Et malgré l'anticipation des retenues, la propagation est assez lente. les additionneurs à propagation de retenue auront terminé leur travail bien avant. Un exemple est celui de l'additionneur CMOS 4008, un additionneur de 4 bit. Il est composé en trois sections. Une première couche de demi-additionneurs calcule les signaux P et G utilisés à la fois pour l'anticipation de la retenue sortante, que pour calculer les bits de somme. Le circuit de calcul de la retenue sortante utilise l'anticipation de retenue. Le reste du circuit fait l'addition en propageant les retenues. [[File:CMOS 4008, circuit découpé en sections.png|centre|vignette|upright=1.5|CMOS 4008, circuit découpé en sections]] ====Les additionneurs à anticipation de retenue multi-niveau==== Il est possible d'utiliser l'anticipation de retenue entre deux blocs. Par exemple, il est possible de créer un additionneur 16 bits en utilisant 4 additionneurs/blocs de 4 bits. L'additionneur utilisé peut être un additionneur à propagation de retenue, ou à anticipation de retenue, peu importe. Pour cela, les additionneurs de 4 bits doivent fournir deux sorties P et G. Les deux sorties indiquent que le bloc soit a généré une retenue, soit a propagé la retenue entrante. Par propagé, on veut dire que la retenue entrante du bloc s'est retrouvée sur la sortie de retenue du bloc. C'est le cas si les 4 colonnes propagent la retenue, ce qui signifie que : : <math>P_\text{4 bits} = P_0 \cdot P_1 \cdot P_2 \cdot P_3</math> Pour la génération, cela veut dire qu'une colonne a générée une retenue, qui a été propagée jusqu'à la sortie. En clair, pour chaque colonne, il faut que le G = 1, et que les signaux P des colonnes soient à 1. Pour les 4 colonnes, cela donne : : <math>G_\text{4 bits} = G_3 + G_2 \cdot P_3 + G_1 \cdot P_3 \cdot P_2 + G_0 \cdot P_3 \cdot P_2 \cdot P_1</math> [[File:Cla4bitsPG.png|centre|vignette|upright=2|Additionneur à anticipation de retenue de 4 bits.]] Pour combiner 4 blocs de 4 bits, on devra donc combiner 4 bits P et G, avec un circuit d'anticipation de retenue. [[File:16-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 16 bits.]] Il est même possible d'aller plus loin et de combiner 4 additionneurs précédents pour obtenir un additionneur 64 bits. [[File:64-bit lookahead carry unit.svg|centre|vignette|upright=2|Additionneur à anticipation de retenue de 64 bits.]] Le résultat est un additionneur à plusieurs niveaux d’anticipation de retenue. Une anticipation de retenue dans un blocs de 4 bits (facultative), entre blocs de 4 bits, entre blocs de 16 bits. La même logique peut être utilisée avec des blocs de taille différente de 4, 16 et 64 bits. ==L'addition signée et la soustraction== Après avoir vu l'addition, il est logique de passer à la soustraction, les deux opérations étant très proches. Si on sait câbler une addition entre entiers positifs, câbler une soustraction n'est pas très compliqué. De plus, la soustraction permet de faire des additions de nombres signés. ===Le soustracteur pour opérandes entiers=== Pour soustraire deux nombres entiers, on peut adapter l'algorithme de soustraction utilisé en décimal, celui que vous avez appris à l'école. Celui-ci ressemble fortement à l'algorithme d'addition : on soustrait les bits de même poids, et on propage éventuellement une retenue sur la colonne suivante. À la différence de l'addition, la retenue est soustraite, et non ajoutée. La table de soustraction nous dit quel est le résultat de la soustraction de deux bits. La voici : * 0 - 0 = 0 ; * 0 - 1 = 1 et une retenue ; * 1 - 0 = 1 ; * 1 - 1 = 0. [[File:Algebra1 05 fig014.svg|centre|vignette|Soustraction en binaire, avec les retenues en rouge.]] La table de soustraction peut servir de table de vérité pour construire un circuit qui soustrait deux bits. Celui-ci est appelé un '''demi-soustracteur'''. Il ressemble beaucoup à un demi-additionneur, les différences se résumant à une porte NON ajoutée pour le calcul de la retenue. [[File:Half Subtractor Vektor.svg|centre|vignette|Demi-soustracteur.]] Comme pour l'additionneur, deux demi-soustracteurs peuvent être combinés pour donner un '''soustracteur complet'''. Le calcul de la retenue se fait en combinant les deux retenues des demi-soustracteurs avec une porte OU. Les soustracteurs complets sont utilisés pour créer des soustracteurs à propagation de retenue ou tout autre circuit soustracteur, sur le même modèle que les additionneurs. [[File:FullSubtractor.svg|centre|vignette|upright=2|Soustracteur complet.]] Vous l'aurez sans doute remarqué, mais le demi-soustracteur ressemble beaucoup au demi-additionneur. La seule différence est une porte NON ajoutée au bon endroit dans le demi-soustracteur. {| |[[File:Half-adder.svg|vignette|Demi-additionneur]] |[[File:Half Subtractor Vektor.svg|vignette|upright=1.3|Demi-soustracteur]] |} La conséquence est qu'il est possible de créer un circuit capable de faire à la fois des additions et des soustractions. L'idée est de remplacer la porte NON du demi-soustracteur par un inverseur commandable. Si on envoie un zéro sur l'entrée de commande, l'inverseur commandable se comportera comme une porte OUI. Le circuit sera alors identique à un demi-additionneur. Si on envoie un 1 sur l'entrée de commande, l'inverseur commandable se comportera comme une porte NON. le circuit sera alors un demi-soustracteur. Il faut faire cela pour chaque demi-soustracteur, ce qui donne ceci pour un soustracteur complet. le résultat est alors appelé un '''additionneur-soustracteur complet'''. [[File:Additionneur-soustracteur complet.png|centre|vignette|upright=2|Additionneur-soustracteur complet]] ===L'additionneur-soustracteur pour opérandes codées en complément à deux=== Étudions le cas de la soustraction en complément à deux, dans l'objectif de créer un circuit soustracteur. Vous savez sûrement que a−b et a+(−b) sont deux expressions équivalentes. Et en complément à deux, − b = not(b) + 1. Dit autrement, a − b = a + not(b) + 1. On pourrait se dire qu'il faut deux additionneurs pour faire le calcul, mais la majorité des additionneurs possède une entrée de retenue pour incrémenter le résultat de l'addition. Un soustracteur en complément à deux est donc simplement composé d'un additionneur et d'un inverseur. [[File:Additionneur soustracteur.png|centre|vignette|upright=2|Soustracteur en complément à deux.]] Il est possible de créer un circuit capable d'effectuer soit une addition, soit une soustraction : il suffit de remplacer l'inverseur par un inverseur commandable, qui peut être désactivé. On a vu comment créer un tel inverseur commandable dans le chapitre sur les circuits combinatoires. On peut remarquer que l'entrée de retenue et l'entrée de commande de l'inverseur sont activées en même temps : on peut fusionner les deux signaux en un seul. [[File:Additionneur-soustracteur en complément à deux.png|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux.]] Une implémentation alternative est la suivante. Elle remplace l'inverseur commandable par un multiplexeur. [[File:4-bit ripple carry adder-subtracter.svg|centre|vignette|upright=2|Additionneur-soustracteur en complément à deux, version alternative.]] ===L'additionneur-soustracteur pour opérandes codées en signe-magnitude=== Passons maintenant aux nombres codés en signe-valeur absolue, les deux opérandes étant notées A et B. Suivant les signes des deux opérandes, on a quatre cas possibles : A + B, A − B (B négatif), −A + B (A négatif) et −A − B (A et B négatifs). Une astuce est que le circuit n'a besoin que de calculer A + B et A − B : il peut les inverser pour obtenir − A − B ou B − A. A + B et A − B peuvent se calculer avec un additionneur-soustracteur, reste à corriger le résultat. Il suffit de lui ajouter un inverseur commandable pour obtenir le circuit d'addition finale. [[File:Additionneur en signe-valeur absolue.png|centre|vignette|upright=2|Additionneur en signe-valeur absolue.]] Toute la difficulté tient dans le calcul du bit de signe du résultat, quand interviennent des soustractions. Autant l'addition de deux nombres de même signe (A + B et −A − B) ne pose aucun problème, autant les soustractions posent problème (A − B et −A + B). Suivant que <math>A<B</math> ou que <math>A>B</math>, le signe du résultat ne sera pas le même. Déterminer le signe du résultat se fait en regardant les bits de débordement d'entier, comme on le verra plus bas. ===L'additionneur-soustracteur pour opérandes codées en représentation par excès=== Passons maintenant aux nombres codés en représentation par excès. On pourrait croire que ces nombres s'additionnent comme des nombres non-signés, mais ce serait oublier la présence du biais, qui pose problème. Dans les cas de nombres signés gérés avec un biais, voyons ce que donne l'addition de deux nombres : : <math>( n_1 + biais ) + ( n_2 + biais ) = n_1 + n_2 + 2 \times biais</math> Or, le résultat correct serait : : <math>n_1 + n_2 + biais</math> En effectuant l'addition telle quelle, le biais est compté deux fois. On doit donc le soustraire après l'addition pour obtenir le résultat correct. Même chose pour la soustraction qui donne ceci : : <math>(n_1 + biais) - (n_2 + biais) = n_1 - n_2</math> Or, le résultat correct serait : : <math> ( n_1 - n_2 ) + biais </math> Il faut rajouter le biais pour obtenir l'exposant correct. On a donc besoin de deux additionneurs/soustracteurs : un pour additionner/soustraire les représentations binaires des opérandes, et un autre pour ajouter/retirer le biais en trop/manquant. ==L'additionneur BCD== Maintenant, voyons un additionneur qui additionne deux entiers au format BCD. Pour cela, nous allons devoir passer par deux étapes. La première est de créer un circuit capable d'additionneur deux chiffres BCD. Ensuite, nous allons voir comment enchaîner ces circuits pour créer un additionneur BCD complet. ===L'additionneur BCD qui fait l'opération chiffre par chiffre=== Nous allons commencer par voir un additionneur qui additionne deux chiffres en BCD, une sorte d'équivalent BCD de l'additionneur complet. Il fournit un résultat sur 4 bits et une retenue qui est mise à 1 si le résultat dépasse 10 (la limite d'un chiffre BCD). Les deux opérandes sont des chiffres BCD codés sur 4 bits et sont additionnés en binaire par un additionneur des plus normaux, similaire à ceux vus plus haut. Le résultat est alors un entier codé en binaire, sur 5 bits, qu'on corrige/convertit pour obtenir un chiffre BCD et une retenue sortante. Pour corriger le résultat, une idée intuitive serait de prendre le résultat et de faire une division par 10. Le quotient donne la retenue, alors que le reste est le résultat, le chiffre BCD. Mais un circuit diviseur par 10 utilise beaucoup de portes logiques, ce qui ne vaut pas le coup. Une autre méthode détecte si le résultat est égal ou supérieur à 10, ce qui correspond à un "débordement" (on dépasse les limites d'un chiffre BCD). Si le résultat est plus petit que 10, il n'y a rien à faire : le résultat est bon et la retenue est de zéro. Par contre, si le résultat vaut 10 ou plus, il faut corriger le résultat et générer une retenue à 1. Il faut donc ajouter un circuit qui détecte si le résultat est supérieur à 9, qui calcule directement la retenue. Ce circuit peut se fabriquer simplement à partir de sa table de vérité, ou en utilisant les techniques que nous verrons dans un chapitre ultérieur sur les comparateurs. La solution la plus simple est clairement d'utiliser la table de vérité, ce qui est très simple, assez pour être laissé en exercice au lecteur. Pour comprendre comment corriger le résultat, établissons une table de vérité qui associe le résultat et le résultat corrigé. L'entrée vaut au minimum 10 et au maximum 9 + 9 = 18. On considère la sortie comme un tout, la retenue étant un 5ème bit, le bit de poids fort. {|class="wikitable" |- ! colspan="5" | Entrée ! ! rowspan="10" | ! Retenue ! Résultat corrigé (sans retenue) ! interprétation de la sortie en binaire (retenue inclue) |- | 0 || 1 || 0 || 1 || 0 | (10) | 1 || 0000 | (16) |- | 0 || 1 || 0 || 1 || 1 | (11) | 1 || 0001 | (17) |- | 0 || 1 || 1 || 0 || 0 | (12) | 1 || 0010 | (18) |- | 0 || 1 || 1 || 0 || 1 | (13) | 1 || 0011 | (19) |- | 0 || 1 || 1 || 1 || 0 | (14) | 1 || 0100 | (20) |- | 0 || 1 || 1 || 1 || 1 | (15) | 1 || 0101 | (21) |- | 1 || 0 || 0 || 0 || 0 | (16) | 1 || 0110 | (22) |- | 1 || 0 || 0 || 0 || 1 | (17) | 1 || 0111 | (23) |- | 1 || 0 || 0 || 1 || 0 | (18) | 1 || 1000 | (24) |} En analysant le tableau, on voit que pour corriger le résultat, il suffit d'ajouter 6. La raison est que le résultat déborde d'un nibble à 16 en binaire, mais à 10 en décimal : il suffit d'ajouter la différence entre les deux, à savoir 6, et le débordement binaire fait son travail. Donc, la correction après une addition est très simple : si le résultat dépasse 9, on ajoute 6. On peut maintenant implémenter l'additionneur BCD, en combinant le comparateur avec 10, le circuit de correction, et l'additionneur. La première solution calcule deux versions du résultat : la version corrigée, la version normale. Le choix entre les deux est réalisée par un multiplexeur, commandé par le comparateur. [[File:Additionneur BCD.png|centre|vignette|upright=1.5|Additionneur BCD]] L'autre solution utilise un circuit commandable qui soit additionne 6, soit ne fait rien. Le choix entre les deux est commandé par le bit calculé par le comparateur. [[File:Additionneur BCD, seconde version.png|centre|vignette|upright=1.5|Additionneur BCD, seconde version.]] Une version alternative du circuit précédent est la suivante. Il contient deux additionneurs : un pour additionner les deux chiffres BCD, un autre pour additionner 6 si besoin. Le résultat du comparateur est directement utilisé pour générer l'opérande du second additionneur : 0 ou 6. Le circuit est simple à concevoir, mais gaspille beaucoup de circuit. Idéalement, il vaudrait mieux utiliser un circuit combinatoire d'addition avec une constante. [[File:Adder 4 Bit BCD.svg|centre|vignette|upright=2|Additionneur BCD, circuit complet.]] Pour obtenir un additionneur BCD complet, il suffit d’enchaîner les additionneurs précédents, comme on le ferait avec les additionneurs complets dans un additionneur à propagation de retenue. Au final, l'additionneur BCD est beaucoup plus compliqué qu'un additionneur normal, car il rajoute un comparateur ">9", un petit additionneur pour ajouter 6 et éventuellement d'autres circuits. De plus, il est difficile d'appliquer les optimisations disponibles sur les additionneurs non-BCD. Notamment, les circuits d'anticipation de retenue sont totalement à refaire et le résultat est relativement compliqué. C'est ce qui explique pourquoi le BCD a progressivement été abandonné au profit du binaire simple. La soustraction en BCD se fait comme en binaire : le nombre à soustraire est remplacé par son complément, le circuit additionne le complément et l'autre opérande, le débordement d'entier fait que le résultat marche. Sauf qu'ici, le complément est un complément à 9. Il se calcule chiffre par chiffre : chaque chiffre est remplacé par (9 - le chiffre en question). ===L'additionneur BCD par ajustement décimal=== L'additionneur BCD précédent effectuait son travail chiffre BCD par chiffre BCD, mais il existe des additionneurs BCD qui font autrement. Sur les premiers processeurs x86, il n'y avait pas d'opération d'addition BCD proprement dit, seulement une addition binaire normale de 8, 16 ou 32 bits. Par contre, elle était secondée par une opération dite d''''ajustement décimal''' qui transformait un nombre binaire en nombre codé en BCD. L'opération d'ajustement décimal prenait un opérande de 8 bits codé en binaire et fournissait un résultat de la même taille, c'est à dire deux chiffres BCD. Effectuer une addition BCD demandait donc de faire deux opérations à la suite : une addition binaire simple, suivie par l'opération d'ajustement décimal. Cela permettait de gérer des nombres entiers en binaire usuel et des entiers BCD sans avoir deux instructions d'addition séparées pour les deux, sans compter que cela simplifiait aussi les circuits d'addition. L'ajustement décimal s'effectue en ajoutant une constante bien précise à l'opérande à convertir en BCD. L'idée est que la constante est découpée en morceaux de 4 bits, correspondant chacun à un chiffre BCD de l'opérande, chaque morceau contenant soit un 0, soit 6. Cela permet d'ajouter soit 0, soit 6, à chaque chiffre BCD, et donc de le corriger. La propagation des retenues d'un chiffre à l'autre est effectuée automatiquement par l'addition binaire de la constante. L'opération d'ajustement décimal calcule automatiquement la constante. Elle découpe l'opérande en ''nibbles'', vérifie si chaque ''nibble'' est supérieur ou égal à 10, puis détermine la valeur de chaque ''nibble'' de la constante finale. Par exemple, si je prends l'opérande 1001 1110, le ''nibble'' de poids faible déborde, alors que celui de poids fort non. La constante sera donc 0000 0110 : 0x06. Inversement, si le ''nibble'' de poids fort déborde et pas celui de poids faible, la constante sera alors 0x60. Et la constante est de 0x66 si les deux ''nibbles'' débordent, de 0x00 si aucun ne déborde. Le circuit d’ajustement décimal est donc composé de trois étapes : deux étapes pour calculer la constante, et un circuit d'addition pour additionner cette constante au nombre de départ. La première étape découpe l'opérande en morceaux de 4 bits, en chiffres BCD, et vérifie si chacun d'entre eux vaut 10 ou plus. La seconde étape prend les résultats de la première étape, et les combine pour calculer la constante. Enfin, on trouve l'addition finale, qui était réalisée par un circuit d'addition utilisé à la fois pour l'ajustement décimal et l'addition binaire. La différence entre une addition normale et une opération d'ajustement décimal tient dans le fait que les deux premières étapes sont désactivées dans une addition normale. [[File:Additionneur BCD parallèle.png|centre|vignette|upright=1.5|Additionneur BCD parallèle]] ===L'additionneur biquinaire=== Les entiers BCD ne sont qu'un des encodages hybrides entre décimal et binaire. L'encodage biquinaire est l'un d'entre eux et nous allons faire un rappel rapide à ce sujet. Pour simplifier, un chiffre encodé en biquinaire est composé de deux parties : un bit, couplé à une partie quinaire encodée en représentation ''one-hot''. La partie quinaire encode un nombre allant de 0 à 4, ce qui prend 5 bits (0, 1, 2, 3 et 4). Le bit indique s'il faut ou non ajouter 5 à la valeur encodée par la partie quinaire. Ainsi, on peut coder tous les nombres de 0 à 9. Additionner deux nombres de biquinaire demande donc d'additionner deux parties quinaires encodées en ''one-hot'' et d'additionner deux bits. Mais attention : il faut tenir compte de la retenue de l'addition des parties quinaires. Et idéalement, il faut aussi tenir compte d'une retenue entrante, provenant de l'addition de la colonne de chiffres précédente. Toute la difficulté vient de la création de l'additionneur ''one-hot''. Heureusement, vu qu'il n'y a que 4-5 bits à additionner, il est souvent fabriqué à partir de sa table de vérité. [[File:Additionneur bi-quinaire.png|centre|vignette|upright=2|Additionneur bi-quinaire]] Un avantage du biquinaire est que le calcul du complément à 9 est très simple. Il faut pour cela : inverser la partie binaire avec une porte NON, puis inverser l'ordre des bits de la partie quinaire. Concrètement, le bit de poids faible devient le bit de poids fort, et ainsi de suite. Par exemple, une partie quinaire 01000 devient 00010, 10000 devient 00001, 00100 ne change pas, etc. Le tout peut se calculer avec une porte NON et 5 multiplexeurs. ===L'additionneur BCD avec calculs intermédiaires en biquinaire=== L'ordinateur IBM 1401, un ancien ''mainframe'' des années 60, utilisait un additionneur BCD un peu particulier. Les nombres étaient encodés en BCD dans la mémoire de l'ordinateur, mais les circuits de calcul utilisaient la représentation biquinaire. Lors d'un calcul, le processeur de l'ordinateur traduisait les chiffres BCD en représentation biquinaire, faisait une addition en biquinaire, avant de traduire le résultat en BCD normal. Pour être précis, l'IBM 1401 utilisait une variante du biquinaire. L'encodage biquinaire de l'IBM 1401 est le suivant : la partie binaire disait si le chiffre était pair ou non, la partie quinaire encodait les valeurs 0, 2, 4, 6 et 8. Le chiffre se calculait en additionnant la partie binaire (0 ou 1) au nombre pair encodé par la partie quinaire. Si l'IBM 1401 utilisait cette variante du biquinaire, c'est car elle donnait des circuits de conversion BCD-biquinaire plus économes en portes logiques et plus rapides. La partie binaire est le bit de poids faible du chiffre BCD, la partie biquinaire est calculée par un simple décodeur qui prend en entrée le chiffre BCD, amputé de son bit de poids faible. La traduction inverse demande d'utiliser un encodeur, à la place du décodeur. Par contre, le circuit d'addition biquinaire était plus compliqué du fait de la gestion des retenues. L'addition des parties binaires et quinaires se faisait en parallèle, dans deux additionneurs séparés. Cependant, l'addition des parties binaire fournit une retenue, qu'il faut prendre en compte. Pour cela, l'IBM 1401 disposait d'un troisième additionneur qui fournissait le résultat final, encodé en biquinaire. [[File:Additionneur bi-quinaire de l'IBM 1401.png|centre|vignette|upright=2|Additionneur biquinaire de l'IBM 1401]] Une implémentation moderne demanderait d'utiliser des portes ET combinées à des portes OU, le circuit pouvant être construit simplement à partir de sa table de vérité. Sur l'IBM 1401, le circuit était cependant différent, en raison de l'utilisation de OU câblés, des croisements de fils qui fonctionnent comme des portes OU, que nous n'avons pas encore vu pour le moment, mais qui seront détaillés dans quelques chapitres. Les OU câblés étaient utilisés pour simplifier le design du circuit, mais demandaient des portes logiques spécifiques, ce qui collait avec le fait que ce ''mainframe'' utilisait des transistors en Germanium. L'implémentation exacte est décrite dans cet article de blog, mais je ne recommande sa lecture qu'à ceux qui savent ce qu'est un OU câblé : * [https://www.righto.com/2015/10/qui-binary-arithmetic-how-1960s-ibm.html Qui-binary arithmetic: how a 1960s IBM mainframe does math]. ==Les débordements d'entier lors d'une addition/soustraction== Les instructions arithmétiques manipulent des entiers codés sur un nombre fixe de bits, qui ne peuvent prendre leurs valeurs que dans un intervalle. Pour les nombres positifs, un ordinateur qui code ses entiers sur n bits pourra coder tous les entiers allant de 0 à <math>2^n -1</math>. Pour les nombres négatifs, l'intervalle est différent et dépend de la représentation utilisée. Dans le cas général, l'ordinateur peut coder les valeurs comprises de <math>N_\text{min}</math> à <math>N_\text{max}</math>. Si le résultat d'un calcul sort de cet intervalle, il ne peut pas être représenté par l'ordinateur et il se produit ce qu'on appelle un '''débordement d'entier'''. La '''valeur haute de débordement''' désigne la première valeur qui est trop grande pour être représentée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 0 et 7, la valeur haute de débordement est égale à 8. On peut aussi définir la '''valeur basse de débordement''', qui est la première valeur trop petite pour être codée par l'ordinateur. Par exemple, pour un ordinateur qui peut coder tous les nombres entre 8 et 250, la valeur basse de débordement est égale à 7. Pour les nombres entiers, la valeur haute de débordement vaut <math>N_\text{max} + 1</math> , alors que la valeur basse vaut <math>N_\text{min} - 1</math> (avec <math>N_\text{max}</math> et <math>N_\text{min}</math> respectivement la plus grande et la plus petite valeur codable par l'ordinateur). ===La correction des débordements d'entier : l'arithmétique saturée=== Quand un débordement d'entier survient, tous les circuits de calcul ne procèdent pas de la même manière. Dans les grandes lignes, il y a deux réactions possibles : soit on corrige automatiquement le résultat du débordement, soit on ne fait rien et on se contente de détecter le débordement. Si le débordement n'est pas corrigé automatiquement, le circuit ne conserve que les bits de poids faibles du résultat. Les bits en trop sont simplement ignorés. On dit qu'on utilise l''''arithmétique modulaire'''. Le problème avec ce genre d'arithmétique, c'est qu'une opération entre deux grands nombres peut donner un résultat très petit. Par exemple, si je dispose de registres 4 bits et que je souhaite faire l'addition 1111 + 0010 (ce qui donne 15 + 2), le résultat est censé être 10001 (17), ce qui est un résultat plus grand que la taille d'un registre. En conservant les 4 bits de poids faible, j’obtiens 0001 (1). En clair, un résultat très grand est transformé en un résultat très petit. Cela peut poser problèmes si on travaille uniquement avec des nombres positifs, mais c'est aussi utilisé pour coder des nombres en complément à deux. D'autres circuits utilisent ce qu'on appelle l''''arithmétique saturée''' : si un calcul génère un débordement, on arrondi le résultat au plus grand entier supporté par le circuit. Les circuits capables de calculer en arithmétique saturée sont un peu plus complexes, vu qu'il faut rajouter des circuits pour corriger le résultat en cas de débordement. Il suffit généralement de rajouter un ''circuit de saturation'', qui prend en entrée le résultat et le corrige en cas de débordement. Ce circuit de saturation met la valeur maximale en sortie si un débordement survient, mais se contente de recopier le résultat du calcul sur sa sortie s'il n'y a pas de débordement. Typiquement, il est composé d'une couche de multiplexeurs, qui sélectionnent quelle valeur mettre sur la sortie : soit le résultat du calcul, soit le plus grand nombre entier géré par le processeur, soit le plus petit (pour les nombres négatifs/soustractions). L'arithmétique saturée est utilisée pour les additions et soustractions, mais c'est plus rare pour les multiplications/divisions. Une des raisons est que le résultat d'une addition/soustraction prend un bit de plus que le résultat, là où les multiplications doublent le nombre de bits. Quand une addition déborde, le résultat réel est proche de la valeur maximale codable. mais quand une multiplication déborde, le résultat peut parfois valoir 200 à 60000 fois plus que la valeur maximale codable. Les calculs avec une valeur saturée/corrigée sont donc crédibles pour une suite d'additions, mais pas pour une suite de multiplications. ===La détection des débordements entiers=== Quand un débordement d'entier a eu lieu, il vaut mieux que l'additionneur prévienne ! Pour cela, l'additionneur a une '''sortie de débordement''', parfois nommée ''Overflow'', dont la valeur indique si l'addition a généré un débordement d'entier ou non. Reste que détecter un débordement ne se fait pas de la même manière selon que l'on parle d'un additionneur non-signé ou signé. Pour les additionneur non-signés, l'additionneur calcule un bit de plus que ce qui est supporté par l'ordinateur. Par exemple, un additionneur 32 bits fournit un résultat sur 33 bits, un débordement d'entier a lieu quand le 33ème bit est à 1. Précisément, la sortie de débordement n'est autre que la retenue finale, celle fournie par le dernier additionneur complet. Le seul type de débordement possible est un débordement par le haut, où le résultat dépasse la valeur maximale. Avec l'arithmétique saturée, le circuit de saturation consiste en une seule couche de multiplexeurs, voire en un circuit de mise à la valeur maximale tel que vu dans le chapitre sur les opérations bits à bits. [[File:Gestion des débordements d'entiers.png|centre|vignette|upright=2.5|Gestion des débordements d'entiers lors d'une addition non-signée.]] Pour les additionneurs non-signés, la gestion des débordements d'entiers dépend fortement de la représentation signée. Nous allons étudier le cas du complément à deux. Si vous vous rappelez le chapitre 1, les calculs sur des nombres en complètement à deux utilisent les règles de l'arithmétique modulaire, c'est une condition nécessaire. À priori, on peut penser que dans ces conditions, les débordements d'entiers sont une chose parfaitement normale, qui nous permet d'avoir des résultats corrects. Néanmoins, certains débordements d'entiers peuvent survenir malgré tout et produire des bugs assez ennuyeux. Si l'on tient en compte les règles du complément à deux, on sait que le bit de poids fort (le plus à gauche) permet de déterminer si le nombre est positif ou négatif : il indique le signe du nombre. Tout se passe comme si les entiers en complément à deux étaient codés sur un bit de moins, et avaient leur longueur amputé du bit de poids fort. Si le résultat d'un calcul écrase le bit de poids fort, il y a un débordement d'entiers. Il existe une règle simple qui permet de détecter ces débordements d'entiers. L'addition de deux nombres positifs ne peut pas être un nombre négatif. Si on additionne deux nombres dont le bit de signe est à 0 et que le bit de signe du résultat est à 1, on est en face d'un débordement d'entiers. Même chose pour deux nombres négatifs : le résultat de l'addition ne peut pas être positif. On peut résumer cela en une phrase : si deux nombres de même signe sont ajoutés, un débordement a lieu quand le bit du signe du résultat a le signe opposé. Modifier les circuits d'au-dessus pour qu'ils détectent les débordements en complément à deux est simple comme bonjour : il suffit créer un petit circuit combinatoire qui prenne en entrée les bits de signe des opérandes et du résultat, et qui fasse le calcul de l'indicateur de débordements. Si l'on rédige sa table de vérité, on doit se retrouver avec la table suivante : {|class="wikitable" |- !Entrées !Sortie |- |000||0 |- |001||1 |- |010||0 |- |011||0 |- |100||0 |- |101||0 |- |110||1 |- |111||0 |} L'équation de ce circuit est la suivante, avec <math>S_a</math> et <math>S_b</math> les signes des deux opérandes, et <math>C_i</math> la retenue de la colonne précédente : : <math> ( S_a . S_b . \overline{C_i} ) + ( \overline{S_a} . \overline{S_b} . C_i )</math> En simplifiant, on obtient alors : : <math>( S_a . S_b ) \oplus C_i</math> Or, il se trouve que <math>S_a . S_b</math> est tout simplement la retenue en sortie du dernier additionneur, que nous noterons <math>C_o</math>. On trouve donc : : <math>C_o \oplus C_i</math> Il suffit donc de faire un XOR entre la dernière retenue et la précédente pour obtenir le bit de débordement. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de décalage et de rotation | prevText=Les circuits de décalage et de rotation | next=Les circuits de comparaison | nextText=Les circuits de comparaison }} </noinclude> 015y0qupry6q2cxcffkknshrpa5gvnm Mathc matrices/Sommaire 0 69175 768473 756908 2026-06-24T08:22:50Z Xhungab 23827 768473 wikitext text/x-wiki __NOTOC__ [[Catégorie:Mathc matrices (livre)]] : * [[Mathc matrices/Introduction|Introduction]] ---- ---- : {{Partie{{{type|}}}| '''Propriétés et Applications'''}} {| class="wikitable" |+ |- | '''Utilitaires pour Octave''' * [[Mathc matrices/a27| Fonctions pour les matrices]] * [[Mathc matrices/04g| Le code de quelques fonctions]] * [[Mathc matrices/03b| Utilitaires graphiques]] * [[Mathc matrices/04m| Exemples d'applications]] * [[Mathc matrices/04l| Ecrire des fonctions mathématiques]] || '''Utilitaires pour le langage C''' * [[Mathc matrices/a33|'''Utilitaires pour le langage C''']] *. *. *. *. |- | '''Les matrices''' [https://youtube.com/playlist?list=PLi6peGpf8EPOx2Pm_rspnagtdkBYe1t6J&feature=shared '''Playlist'''] : * [[Mathc matrices/05q|Créer une matrice ]] : * [[Mathc matrices/e12d2|Afficher une matrice ]] : * [[Mathc matrices/a03c|Afficher une matrice dans un fichier]] : * [[Mathc matrices/Fichiers c : mul_tran|Afficher une matrice pour Octave:]] : * [[Mathc matrices/a07|Copier une matrice]] : * [[Mathc matrices/c12eb1|Matrices aléatoires]] : * [[Mathc matrices/01p|Éntrez vos données]] : * [[Mathc matrices/c12bn|Tableaux de matrices]] : * [[Mathc matrices/a94|Afficher des vecteurs d'une colonne]] : : '''Opérations de bases''' : * [[Mathc matrices/c12ea2|Opérations sur les matrices]] : * [[Mathc matrices/c12ea1|La fonction trace_R();]] : * [[Mathc matrices/03o|La fonction transpose_R();]] *. *. : : || '''Les matrices spécifiques''' : * [[Mathc matrices/c12fn17|Matrice identité]] : * [[Mathc matrices/c12b8|Matrices triangulaires]] : * [[Mathc matrices/e02a|Matrices commutatives]] : * [[Mathc matrices/a90|Matrices semblables]] : * [[Mathc matrices/c12b3|Matrices symétriques]] : * [[Mathc matrices/c12b1|Matrices anti-symétriques]] : * [[Mathc matrices/02h|Matrice centrosymétrique]] : * [[Mathc matrices/02v|Matrices définies positives]] : * [[Mathc matrices/035|Matrices définies négatives]] : * [[Mathc matrices/008|Matrices de Hankel]] : * [[Mathc matrices/009|Matrices de Toeplitz]] : * [[Mathc matrices/a76|La fonction exponentielle]] : : '''Application Graphiques''' : * [[Mathc matrices/e02|Matrices de transformation [2x2]]] : * [[Mathc matrices/a133|Matrices de transformation [3x3]]] : : |- | '''Déterminant''' [https://youtube.com/playlist?list=PLi6peGpf8EPO6GuKOJERdVXKu_zdExd9_&si=1P0vkGzm5Mrf9Vf2 '''Playlist'''] : * [[Mathc matrices/b03|Le déterminant]] : * [[Mathc matrices/Fichiers c : fp_e_mr| Opérations élémentaires]] : * [[Mathc matrices/e12d9|Les fonctions intermédiaires]] : * [[Mathc matrices/c21n|Quelque propriétés ]] : : '''Applications en mathématique ''' : * [[Mathc matrices/149|Matrice Adjointe]] : * [[Mathc matrices/e12d7|L'inverse par le déterminant]] ; * [[Mathc matrices/a235|Produit en croix]] : : || '''Applications en géométrie ''' : * [[Mathc matrices/25a|L'équation d'une droite]] : * [[Mathc matrices/25b|L'équation d'un plan]] : * [[Mathc matrices/25c|L'équation d'une parabole]] : * [[Mathc matrices/25d|L'équation d'un cercle]] : * [[Mathc matrices/25e|L'équation d'une sphère]] * . * . * . * . : : |- | '''Gauss-Jordan ''' [https://youtube.com/playlist?list=PLi6peGpf8EPODYQZ0fosFTZZqKB9-CkHi '''Playlist'''] : * [[Mathc matrices/a205|Gauss-Jordan Total Pivoting]] : * [[Mathc matrices/a207|L'inverse]] : : '''Application ''' : * [[Mathc matrices/a209|Analyse d'un '''réseau''']] : * [[Mathc matrices/a216|Analyse d'un circuit '''électrique''']] : : '''Applications en géometrie ''' : * [[Mathc matrices/26a|L'équation d'un '''polynôme''']] : * [[Mathc matrices/26b|L'équation d'un '''conique''']] : * [[Mathc matrices/26c|L'équation d'un '''cercle''']] : : '''Applications en mathématique ''' : * [[Mathc matrices/a208|Systèmes '''non linéaire''' ]] : * [[Mathc matrices/a32|Choisir les solutions d'un système]] : : || '''Gauss-Jordan Partial Pivoting ''' : * [[Mathc matrices/a203|Gauss-Jordan Partial Pivoting]] : * [[Mathc matrices/a204|Variables libres]] : : '''Application ''' : * [[Mathc matrices/a201|Équation '''chimique''']] : : '''Applications mathématiques ''' : * [[Mathc matrices/c21s|Trouver une base pour ...]] : * [[Mathc matrices/c24f|Matrices de changement de base]] : * [[Mathc matrices/c24k|Matrice d'une application linéaire]] : * [[Mathc matrices/e05b|Projection sur un sous-espace vectoriel]] *. *. *. *. : : |- | '''Produits scalaires''' [https://youtube.com/playlist?list=PLi6peGpf8EPM0AMbdj2DOnyFYP97-93Ry '''Playlist'''] : * [[Mathc matrices/Fichiers h : a03d0|Produit scalaire]] : * [[Mathc matrices/e05c| Quelques Propriétés]] : * [[Mathc matrices/08o| Calculer les vecteurs orthogonaux]] : : '''Orthogonalisation ''' : * [[Mathc matrices/e05a|Les matrices ortho'''normales''']] : * [[Mathc matrices/c25b|Quelques '''propriétés''']] : : '''La QR Décompositions ''' : * [[Mathc matrices/c12an8|'''La QR décomposition:''']] : : '''Application ''' : * [[Mathc matrices/c22m|Analyse d'un réseau]] : * [[Mathc matrices/c22t|Analyse d'un circuit électrique]] : : '''Applications en mathématique ''' : * [[Mathc matrices/00u|Les coefficients d'un polynôme]] : * [[Mathc matrices/00z|Les coefficients d'un conique]] : * [[Mathc matrices/c23l|Les coefficients d'un cercle]] : * . : * . : * . : : || '''Vecteurs propres ''' : * [[Mathc matrices/e12d6|Vecteurs et valeurs propres]] : * [[Mathc matrices/a147|Quelques '''propriétés''']] : * [[Mathc matrices/03h|Valeurs propres '''multiples'''.]] : : '''Applications en mathématique ''' : * [[ Mathc matrices/01z|Conditionnement matriciel]] : * [[Mathc matrices/e050c|'''Fonctions matricielles''']] : * [[Mathc matrices/09b|'''Système dynamique linéaire discret''']] : * [[Mathc matrices/a29|La décomposition spectral]] : : '''Applications graphique ''' : * [[Mathc matrices/060|'''Formes quadratiques : 2D''']] ; * [[Mathc matrices/061|'''Formes quadratiques : 3D''']] : * [[Mathc matrices/08p| '''Choisir''' les valeurs propres]] : * [[Mathc matrices/03g|'''Projection du plan'''(1)]] : * [[Mathc matrices/08u|'''Projection du plan'''(2)]] : * [[Mathc matrices/a257|'''Projection de l'espace'''(1)]] : * [[Mathc matrices/090|'''Projection de l'espace'''(2)]] : * [[Mathc matrices/062|''' Projection de l'hyperespace'''(1)]] : * [[Mathc matrices/096|'''Projection de l'hyperespace'''(2)]] : : |- | '''Valeurs singulière''' : * [[Mathc matrices/c12an7|Calculer les Valeurs Singulières]] : : '''SVD décomposition''' : * [[Mathc matrices/e12a|Plus de lignes que de colonnes]] : * [[Mathc matrices/02q|Quelques propriétés ]] : * [[Mathc matrices/e12b|Plus de colonnes que de lignes]] *. *. *. *. : : || '''Pseudo inverse: ''' : * [[Mathc matrices/26d|'''Pseudo inverse:''']] : : '''Application ''' : * [[Mathc matrices/00t|Analyse d'un réseau]] : * [[Mathc matrices/00i|Analyse d'un circuit électrique]] : : '''Applications en mathématique ''' : * [[Mathc matrices/088|Étude d'un polynôme]] : * [[Mathc matrices/08b|Étude d'un conique]] : * [[Mathc matrices/00k|Étude d'un cercle]] : : |} : : ---- {{Partie{{{type|}}}| '''La bibliothèque'''}} : {{Partie{{{type|}}}|[[Mathc matrices/c21r| '''La bibliothèque.''']]}} : ---- {{Partie{{{type|}}}| '''Gnuplot.'''}} : * [[Mathc matrices/c21q|Gnuplot:]] {{Lien modifier|Mathc matrices/Sommaire|modifier le sommaire}} {{AutoCat}} crdm9ix728l41kq2ww7ibnme1e25h7w Fonctionnement d'un ordinateur/Les portes logiques 0 72561 768417 755753 2026-06-23T15:47:38Z Mewtow 31375 /* La première méthode : combiner des portes dérivée d'un ET avec un OU */ 768417 wikitext text/x-wiki Le chapitre précédent nous a appris à encoder des nombres en binaire, ce qui est suffisant pour encoder n'importe quelle donnée. Reste à savoir comment un ordinateur fait des opérations sur ces bits. Dans ce chapitre, nous allons voir qu'un ordinateur effectue des opérations très simples sur des bits, opérations qui sont implémentées avec des portes logiques, elles-mêmes fabriquées avec des transistors. Nous allons voir les portes logiques dans ce chapitre, puis comment faire des circuits plus complexes dans les chapitres suivants. ==Les portes logiques de base== Les '''portes logiques''' sont des circuits qui prennent un ou plusieurs bits en entrée et fournissent un bit en guise de résultat. Elles possèdent des entrées sur lesquelles on va placer des bits, et une sortie sur laquelle se trouve le bit de résultat. Les entrées ne sont rien d'autre que des morceaux de « fil » conducteur sur lesquels on envoie un bit (une tension). La sortie est similaire, si ce n'est qu'on récupère le bit de résultat. : '''Sur les schémas qui vont suivre, les entrées des portes logiques seront à gauche et les sorties à droite !''' Les portes logiques ont différent symboles selon le pays et l'organisme de normalisation : * Commission électrotechnique internationale (CEI) ou ''International Electrotechnical Commission'' (IEC), * ''Deutsches Institut für Normung'' (DIN, Institut allemand de normalisation), * ''American National Standards Institute'' (ANSI). ===La porte OUI/BUFFER=== La première porte fondamentale est la porte OUI, qui agit sur un seul bit : sa sortie est exactement égale à l'entrée. En clair, elle recopie le bit en entrée sur sa sortie. Pour simplifier la compréhension, je vais rassembler les états de sortie en fonction des entrées pour chaque porte logique dans un tableau que l'on appelle '''table de vérité'''. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée!!Sortie |- ||0||0 |- ||1||1 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte OUI(BUFFER). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:Buffer IEC Labelled.svg]] | [[Fichier:Buffer DIN.svg]] | [[Fichier:Buffer ANSI Labelled.svg]] |} </div> </div> Mine de rien, la porte OUI est parfois utile. Elle sert surtout pour recopier un signal électrique qui risque de se dissiper dans un fil trop long. On place alors une porte OUI au beau milieu du fil, pour éviter tout problème, la porte logique régénérant le signal électrique, comme on le verra dans le chapitre suivant. Cela lui vaut parfois le nom de porte BUFFER, ce qui veut dire tampon. Les portes OUI sont aussi utilisées dans certaines mémoires RAM (les mémoires SRAM), comme nous le verrons dans quelques chapitres. ===La porte NON=== La seconde porte fondamentale est la porte NON, qui agit sur un seul bit : la sortie d'une porte NON est exactement le contraire de l'entrée. Son symbole ressemble beaucoup au symbole d'une porte OUI, la seule différence étant le petit rond au bout du triangle. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée!!Sortie |- ||0||1 |- ||1||0 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte NON (NOT). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:NOT IEC Labelled.svg]] | [[Fichier:NOT DIN.svg]] | [[Fichier:NOT ANSI Labelled.svg]] |} </div> </div> ===La porte ET=== La porte ET possède plusieurs entrées, mais une seule sortie. Cette porte logique met sa sortie à 1 quand toutes ses entrées valent 1. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||0 |- ||0||1||0 |- ||1||0||0 |- ||1||1||1 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte ET (AND). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:AND IEC Labelled.svg]] | [[Fichier:AND DIN.svg]] | [[Fichier:AND ANSI Labelled.svg]] |} </div> </div> ===La porte NAND=== La porte NAND donne l'exact inverse de la sortie d'une porte ET. En clair, sa sortie ne vaut 1 que si au moins une entrée est nulle. Dans le cas contraire, si toutes les entrées sont à 1, la sortie vaut 0. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||1 |- ||0||1||1 |- ||1||0||1 |- ||1||1||0 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte NON-ET (NAND). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:NAND IEC Labelled.svg]] | [[Fichier:NAND DIN.svg]] | [[Fichier:NAND ANSI Labelled.svg]] |} </div> </div> Au fait, si vous regardez le schéma de la porte NAND, vous verrez que son symbole est presque identique à celui d'une porte ET : seul un petit rond (blanc pour ANSI, noir pour DIN) ou une barre (CEI) sur la sortie de la porte a été rajouté. Il s'agit d'une sorte de raccourci pour schématiser une porte NON. ===La porte OU=== La porte OU est une porte dont la sortie vaut 1 si et seulement si au moins une entrée vaut 1. Dit autrement, sa sortie est à 0 si toutes les entrées sont à 0. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||0 |- ||0||1||1 |- ||1||0||1 |- ||1||1||1 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte OU (OR). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:OR IEC Labelled.svg]] | [[Fichier:OR DIN.svg]] | [[Fichier:OR ANSI Labelled.svg]] |} </div> </div> ===La porte NOR=== La porte NOR donne l'exact inverse de la sortie d'une porte OU. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||1 |- ||0||1||0 |- ||1||0||0 |- ||1||1||0 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte NON-OU (NOR). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:NOR IEC Labelled.svg]] | [[Fichier:NOR DIN.svg]] | [[Fichier:NOR ANSI Labelled.svg]] |} </div> </div> ===La porte XOR=== Avec une porte OU, deux ET et deux portes NON, on peut créer une porte nommée XOR. Cette porte est souvent appelée porte OU exclusif. Sa sortie est à 1 quand les deux bits placés sur ses entrées sont différents, et vaut 0 sinon. <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||0 |- ||0||1||1 |- ||1||0||1 |- ||1||1||0 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte OU-exclusif (XOR). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:XOR IEC Labelled.svg]] | [[Fichier:XOR DIN.svg]] | [[Fichier:XOR ANSI Labelled.svg]] |} </div> </div> ===La porte XNOR=== La porte XOR possède une petite sœur : la XNOR. Sa sortie est à 1 quand les deux entrées sont identiques, et vaut 0 sinon (elle est équivalente à une porte XOR suivie d'une porte NON). <div class="flex-content"> <div class="flex-content-half"> {|class="wikitable" |- !Entrée 1!!Entrée 2!!Sortie |- ||0||0||1 |- ||0||1||0 |- ||1||0||0 |- ||1||1||1 |} </div> <div class="flex-content-half"> {| |+ Symboles d'une porte NON-OU-exclusif (XNOR). ! CEI !! DIN !! ANSI |- style="background-color: #cccccc;" | [[Fichier:XNOR IEC Labelled.svg]] | [[Fichier:XNOR DIN.svg]] | [[Fichier:XNOR ANSI Labelled.svg]] |} </div> </div> ==Interlude propédeutique : combien il y a-t-il de portes logiques différentes ?== Les portes logiques que nous venons de voir ne sont pas les seules. En fait, il existe un grand nombre de portes logiques différentes, certaines ayant plus d'intérêt que d'autres. Mais avant toute chose, nous allons parler d'un point important : combien y a-t-il de portes logiques en tout ? La question a une réponse très claire, pour peu qu'on précise la question. Les portes que nous avons vu précédemment ont respectivement 1 et 2 bits d'entrée, mais il existe aussi des portes à 3, 4, 5, bits d’entrée, voire plus. Il faut donc se demander combien il existe de portes logiques, dont les entrées font N bits. Par exemple, combien y a-t-il de portes logiques avec un bit d'entrée ? Avec deux bits d'entrée ? Avec 3 bits ? Pour cela, un petit raisonnement peut nous donner la réponse. Vous avez vu plus haut qu'une porte logique est définie par une table de vérité, qui liste le bit de sortie pour chaque combinaison possible des entrées. Le raisonnement se fait en deux étapes. La première détermine, pour n bits d'entrée, combien il y a de lignes dans la table de vérité. La seconde détermine combien de tables de vérité à c lignes existent. [[File:Tabla de verdad 2.svg|centre|vignette|upright=2|Les 16 portes logiques à deux entrées possibles.]] Le nombre de lignes de la table de vérité se calcule facilement quand on se rend compte qu'une porte logique reçoit en entrée un "nombre" codé sur n bits, et fournit un bit de résultat qui dépend du "nombre" envoyé en entrée. Chaque ligne de la table de vérité correspond à une valeur possible pour le "nombre" envoyé en entrée. Pour n bits en entrée, la table de vérité fait donc <math>2^n</math> lignes. Ensuite, calculons combien de portes logiques en tout on peut créer c lignes. Là encore, le raisonnement est simple : chaque combinaison peut donner deux résultats en sortie, 0 et 1, le résultat de chaque combinaison est indépendant des autres, ce qui fait : : <math>F = 2^c =2^{2^n}</math>. Pour les portes logiques à 1 bit d’entrée, cela fait 4 portes logiques. Pour les portes logiques à 2 bits d’entrée, cela fait 16 portes logiques. Pour les portes logiques à 3 bits d’entrée, cela fait 256 portes logiques. ==Les portes logiques à un bit d'entrée== Il existe quatre portes logiques de 1 bit. Il est facile de toutes les trouver avec un petit peu de réflexion, en testant tous les cas possibles. * La première donne toujours un zéro en sortie, c'est la porte FALSE ; * La seconde recopie l'entrée sur sa sortie, c'est la porte OUI, aussi appelée la porte BUFFER ; * La troisième est la porte NON vue plus haut ; * La première donne toujours un 1 en sortie, c'est la porte TRUE. {|class="wikitable" |+ Tables de vérité des portes logiques à une entrée |- ! Entrée !! !! FALSE !! OUI !! NON !! TRUE |- | 0 || || 0 || 0 || 1 || 1 |- | 1 || || 0 || 1 || 0 || 1 |} On peut fabriquer une porte OUI en faisant suivre deux portes NON l'une à la suite de l'autre. Inverser un bit deux fois redonne le bit original. [[File:Buffer Gate from Not Gate.png|centre|vignette|Porte OUI/Buffer fabriquée à partie de deux portes NON.]] Les portes logiques TRUE et FALSE sont des portes logiques un peu à part, qu'on appelle des portes triviales. Elles sont absolument inutiles et n'ont même pas de symbole attitré. Il est possible de fabriquer une porte FALSE à partir d'une porte TRUE suivie d'une porte NON, et inversement, de créer une porte TRUE en inversant la sortie d'une porte FALSE. Pour résumer, toutes les portes à une entrée peuvent se fabriquer en prenant une porte NON, couplée avec soit une porte FALSE, soit une porte TRUE. C'est étrange que l'on doive faire un choix arbitraire, mais c'est comme ça et la même chose arrivera quand on parlera des portes à deux entrées. ==Les portes logiques à deux bits d'entrée== Les portes logiques à 2 bits d'entrée sont au nombre de 16. Et dans ces 16 portes, sont inclues les portes logiques à une entrée, à savoir les portes logiques FALSE, TRUE, OUI et NON. La porte OUI est en double, avec une porte qui recopie l'entrée A, une autre qui recopie l'entrée . De même, on trouve deux portes NON : une qui inverse l'entrée A et une autre qui inverse l'entrée B. En clair, sur les 16 portes logiques à deux entrées, 6 d'entre elles sont des portes à une entrée. Elles ont deux entrées, mais l'une d'entre elle n'est pas prise en compte. Seules 10 sont de vraies portes à deux entrées. Dans le tableau ci-dessous, avec les portes à une entrée illustrées en bleu. {|class="wikitable" |- ! Entrée !! FALSE !! NOR !! NCONVERSE !! NON (A) !! NIMPLY !! NON (B) !! XOR !! NAND !! ET !! NXOR !! OUI (B) !! IMPLY !! OUI (A) !! CONVERSE !! OU !! TRUE |- | 00 || class="f_bleu" | 0 || 1 || 0 || class="f_bleu" | 1 || 0 || class="f_bleu" | 1 || 0 || 1 || 0 || 1 || class="f_bleu" | 0 || 1 || class="f_bleu" | 0 || 1 || 0 || class="f_bleu" | 1 |- | 01 || class="f_bleu" | 0 || 0 || 1 || class="f_bleu" | 1 || 0 || class="f_bleu" | 0 || 1 || 1 || 0 || 0 || class="f_bleu" | 1 || 1 || class="f_bleu" | 0 || 0 || 1 || class="f_bleu" | 1 |- | 10 || class="f_bleu" | 0 || 0 || 0 || class="f_bleu" | 0 || 1 || class="f_bleu" | 1 || 1 || 1 || 0 || 0 || class="f_bleu" | 0 || 0 || class="f_bleu" | 1 || 1 || 1 || class="f_bleu" | 1 |- | 11 || class="f_bleu" | 0 || 0 || 0 || class="f_bleu" | 0 || 0 || class="f_bleu" | 0 || 0 || 0 || 1 || 1 || class="f_bleu" | 1 || 1 || class="f_bleu" | 1 || 1 || 1 || class="f_bleu" | |} Les 10 portes logiques restantes peuvent se fabriquer en combinant d'autres portes logiques de base. Par exemple, certaines portes sont l'inverse l'une de l'autre. La porte ET et la porte NAND sont l'inverse l'une de l'autre : il suffit d'en combiner une avec une porte NON pour obtenir l'autre. Même chose pour les portes OU et NOR, ainsi que les portes XOR et NXOR. De fait, la moitié des portes logiques sont l'inverse de l'autre. {|class="wikitable" |- ! Porte ET |[[File:AND from NAND and NOT.svg|class=transparent|AND from NAND and NOT]] |- ! Porte OU |[[File:OR from NOR and NOT.svg|class=transparent|OR from NOR and NOT]] |} Mais dans ce qui suit, nous allons voir que certaines portes logiques sont des dérivées des portes ET et des portes OU, formées en combinant une porte ET/OU avec une ou plusieurs portes NON. Les portes logiques dérivées de la porte ET sont illustrées en rouge dans le tableau suivant, celles dérivées de la porte OU sont en vert, les portes XOR/NXOR sont en jaune, le reste est les portes à une entrée. {|class="wikitable" |- ! Entrée !! !! FALSE !! NOR !! NCONVERSE !! NON A !! NIMPLY !! NON (B) !! XOR !! NAND !! ET !! NXOR !! OUI (B) !! IMPLY !! OUI (A) !! CONVERSE !! OU !! TRUE |- | 00 || || 0 || class="f_vert" | 1 || class="f_vert" | 0 || 1 || class="f_vert" |0 || 1 || class="f_jaune" | 0 || class="f_rouge" | 1 || class="f_vert" | 0 || class="f_jaune" | 1 || 0 || class="f_rouge" | 1 || 0 || class="f_rouge" | 1 || class="f_rouge" | 0 || 1 |- | 01 || || 0 || class="f_vert" | 0 || class="f_vert" | 1 || 1 || class="f_vert" |0 || 0 || class="f_jaune" | 1 || class="f_rouge" | 1 || class="f_vert" | 0 || class="f_jaune" | 0 || 1 || class="f_rouge" | 1 || 0 || class="f_rouge" | 0 || class="f_rouge" | 1 || 1 |- | 10 || || 0 || class="f_vert" | 0 || class="f_vert" | 0 || 0 || class="f_vert" |1 || 1 || class="f_jaune" | 1 || class="f_rouge" | 1 || class="f_vert" | 0 || class="f_jaune" | 0 || 0 || class="f_rouge" | 0 || 1 || class="f_rouge" | 1 || class="f_rouge" | 1 || 1 |- | 11 || || 0 || class="f_vert" | 0 || class="f_vert" | 0 || 0 || class="f_vert" |0 || 0 || class="f_jaune" | 0 || class="f_rouge" | 0 || class="f_vert" | 1 || class="f_jaune" | 1 || 1 || class="f_rouge" | 1 || 1 || class="f_rouge" | 1 ||class="f_rouge" | 1 || 1 |} ===Les portes dérivées de la porte OU=== Les portes dérivées de la porte OU regroupent les deux portes OU et NAND, ainsi que deux nouvelles portes : IMPLY et CONVERSE. Elles sont équivalentes à une porte OU dont on aurait inversé une des entrées. Leurs symboles trahissent cet état de fait, jugez-en vous-même : {| |[[File:Puerta CM.svg|centre|vignette|Porte CONVERSE.]] |[[File:Puerta CMI.svg|centre|vignette|Porte IMPLY.]] |} Vous vous demandez certainement ce qui se passe quand on inverse les deux entrées avant le OU. Un bon moyen de s'en rendre compte serait d'écrire la table de vérité de ce petit circuit, et le résultat que vous retomberez exactement sur la table de vérité d'une porte NAND. En clair, une porte NAND est équivalente à une porte OU dont on aurait inversé les deux entrées. [[File:2. Theorem.svg|centre|vignette|upright=2|Porte NOR fabriquée avec une porte ET et deux portes NON.]] Les portes dérivées d'un OU mettent leur sortie à 1 pour trois lignes de la table de vérité, pour trois entrées possibles. Aussi, on les appellera des '''portes 3-combinaisons'''. {|class="wikitable" |- ! Entrée !! NAND !! OR !! CONVERSE !! IMPLY |- | 00 || class="f_rouge" | 1 || class="f_rouge" | 0 || class="f_rouge" | 1 || class="f_rouge" | 1 |- | 01 || class="f_rouge" | 1 || class="f_rouge" | 1 || class="f_rouge" | 0 || class="f_rouge" | 1 |- | 10 || class="f_rouge" | 1 || class="f_rouge" | 1 || class="f_rouge" | 1 || class="f_rouge" | 0 |- | 11 || class="f_rouge" | 0 || class="f_rouge" | 1 || class="f_rouge" | 1 || class="f_rouge" | 1 |} ===Les portes dérivées de la porte ET=== Les portes dérivées de la porte ET regroupent les deux portes NOR et ET, ainsi que deux nouvelles portes : NCONVERSE et NIMPLY, qui sont respectivement l'inverse des portes CONVERSE et IMPLY. Elles ont une sortie à 1 à condition que l'une des entrées soit à 1, et l'autre entrée soit à 0. On devine rapidement que ces deux portes peuvent se fabriquer en prenant une porte ET et en ajoutant une porte NON sur l'entrée adéquate. Au passage, cela se ressent dans les symboles utilisés pour ces deux portes, qui sont les suivants : {| |- |[[File:Puerta NCM.svg|centre|vignette|Porte NCONVERSE.]] |[[File:Puerta NCMI.svg|centre|vignette|Porte NIMPLY.]] |} Vous vous demandez certainement ce qui se passe quand on inverse les deux entrées avant le ET. Encore une fois, il faut pour cela écrire la table de vérité du circuit. Et le résultat est la table de vérité d'une porte NOR. En clair, une porte NOR est équivalente à une porte ET dont on aurait inversé les deux entrées. [[File:1. Theorem.svg|centre|vignette|upright=2|Porte NOR fabriquée avec une porte ET et deux portes NON.]] Les portes dérivées d'un ET mettent leur sortie à 1 pour une seule combinaison d'entrée, une seule ligne de la table de vérité. Aussi, nous allons les appeler des '''portes 1-combinaison'''. {|class="wikitable" |- ! Entrée !! NOR !! NCONVERSE !! NIMPLY !! ET |- | 00 || class="f_vert" | 1 || class="f_vert" | 0 || class="f_vert" | 0 || class="f_vert" | 0 |- | 01 || class="f_vert" | 0 || class="f_vert" | 1 || class="f_vert" | 0 || class="f_vert" | 0 |- | 10 || class="f_vert" | 0 || class="f_vert" | 0 || class="f_vert" | 1 || class="f_vert" | 0 |- | 11 || class="f_vert" | 0 || class="f_vert" | 0 || class="f_vert" | 0 || class="f_vert" | 1 |} ===Les liens entre portes 1 et 3-combinaisons=== Il y a un lien assez fort entre les ports dérivées de la porte ET et celles dérivées de la porte OU. Pour comprendre pourquoi, regardez le tableau suivant, qui liste les portes 1 et 3-combinaison en paires. On voit que chaque porte 1-combinaison est l'exact inverse d'une porte 3-combinaison ! La conséquence est que l'on peut créer n'importe quelle porte 3-combinaison à partie d'une porte 1-combinaison, et réciproquement. {|class="wikitable" |- ! Entrée !! NOR !! OU !! !! NCONVERSE !! CONVERSE !! !! IMPLY !! NIMPLY !! !! ET !! NAND |- | 00 || class="f_vert" | 1 || class="f_rouge" | 0 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 |- | 01 || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 1 || class="f_rouge" | 0 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 |- | 10 || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 1 || class="f_rouge" | 0 || || class="f_vert" | 0 || class="f_rouge" | 1 |- | 11 || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 0 || class="f_rouge" | 1 || || class="f_vert" | 1 || class="f_rouge" | 0 |} Par exemple, nous avions vu plus haut que la porte NOR est une porte dérivée d'une porte ET. On peut créer une porte OU en ajoutant une porte NON à une porte NOR basée sur un ET, ce qui donne le circuit ci-dessous. Ou encore, nous avions vu plus haut que la porte NAND est une porte dérivée d'une porte OU. On peut créer une porte ET en ajoutant une porte NON à une porte NAND basée sur un OU, ce qui donne le circuit ci-dessous. {| |[[File:Porte OU fabriquée avec des portes NON et ET.png|centre|vignette|upright=1.5|Porte OU fabriquée avec des portes NON et ET.]] |[[File:Porte ET fabriquée avec des portes NON et OU.png|centre|vignette|upright=1.5|Porte ET fabriquée avec des portes NON et OU.]] |} ===Les portes XOR/NXOR sont "superflues"=== Dans cette section, nous allons montrer que les portes XOR/NXOR peuvent se fabriquer à partir d'autres portes logiques. Il y a deux manières pour concevoir une porte XOR/NXOR à partir de portes ET/OU/NON. La première méthode combine plusieurs portes 1-combinaison avec une porte OU. L'autre méthode fait l'inverse : on combine plusieurs portes 3-combinaisons avec une porte ET. ====La première méthode : combiner des portes dérivée d'un ET avec un OU==== Commençons par le cas d'une porte XOR. La sortie d'une porte XOR est à 1 dans deux situations : soit la première entrée est à 1 et l'autre à 0, soit c'est l'inverse. Les deux cas correspondent respectivement aux portes NCONVERSE et NIMPLY, vue précédemment. {|class="wikitable" |- ! Entrée 1 !! Entrée 2!! !! NCONVERSE !! NIMPLY !! !! (NCONVERSE) OU (NIMPLY) = XOR |- ||0||0|| ||0||0|| ||0 |- ||0||1|| ||0||1|| ||1 |- ||1||0|| ||1||0|| ||1 |- ||1||1|| ||0||0|| ||0 |} La sortie des deux circuits est combinée avec une porte OU, car une seule des deux situations rencontrées met la sortie à 1. Le circuit obtenu est le suivant : [[File:XOR als elementaire poorten.png|centre|vignette|upright=1|Porte XOR fabriquée à partir de portes ET/OU/NON.]] : Notons que ce circuit nous donne une idée pour créer une porte NXOR : il suffit de remplacer la porte OU finale par une porte NOR. La porte NXOR peut se concevoir à parti du même raisonnement. La porte NXOR sort un 1 dans deux cas : soit quand ses deux entrées sont à 1, soit quand elles sont toutes deux à 0. La porte ET a sa sortie à 1 dans le premier cas, alors que la porte NOR (une OU suivie d'une NOT) a sa sortie à 1 dans le second cas. {|class="wikitable" |- !Entrée 1!!Entrée 2!! !!NOR!!ET!! !! NXOR |- ||0||0|| ||1||0|| ||1 |- ||0||1|| ||0||0|| ||0 |- ||1||0|| ||0||0|| ||0 |- ||1||1|| ||0||1|| ||1 |} Reste à combiner les deux portes avec une porte OU. Le circuit obtenu est le suivant : [[File:3 gate XNOR.svg|centre|vignette|upright=1|Porte NXOR fabriquée à partir de portes ET/OU/NON, alternative.]] Notons que ce circuit nous donne une troisième possibilité pour créer une porte XOR : il suffit de remplacer la porte OU finale par une porte NOR. [[File:Porte XOR faite avec des portes ET et NOR.png|centre|vignette|upright=1|Porte XOR faite avec des portes ET et NOR.]] Il s'agit là d'une technique qui marche au-delà des portes XOR, et qui marche pour toutes les portes logiques. L'idée est de lister toutes les lignes de la table de vérité où la porte sort un 1. Pour chaque ligne, on prend la porte 1-combinaison adéquate : celle qui sort un 1 pour cette ligne. On effectue ensuite un OU entre toutes les portes dérivées d'un ET. cette technique permet de fabriquer directement toutes les portes logiques à deux entrées, sauf la porte FALSE. C'est la seule qui ne puisse être fabriquée à partir de portes 1-combinaison seules et qui demande d'utiliser une porte NON pour. On peut donc, en théorie, fabriquer toutes les portes logiques à partir de seulement les portes ET, OU et NON. ====La seconde méthode : combiner des portes dérivées d'un OU avec un ET==== Une porte logique peut être conçue avec une méthode opposée à la précédente. Au lieu de procéder par addition, on procède par soustraction. Cette méthode demande de prendre des portes 3-combinaison et de les combiner avec une porte ET. Elle permet de fabriquer toutes les portes logiques, sauf la porte TRUE. Par exemple, prenons la porte XOR. On part du principe qu'un XOR est un OU, sauf dans le cas où les deux entrées sont à 1, cas qui peut se détecter avec une porte ET. Sauf qu'on veut que la porte sorte un 0 quand les deux entrées sont à 1, alors qu'un ET fait l'inverse, ce qui indique qu'on doit plutôt utiliser une porte NAND. Voici ce que cela donne : {|class="wikitable" |- ! Entrée 1 !! Entrée 2!! !! OU !! NAND !! !! XOR |- ||0||0|| ||0||1|| ||0 |- ||0||1|| ||1||1|| ||1 |- ||1||0|| ||1||1|| ||1 |- ||1||1|| ||1||0|| ||0 |} On voit qu'en faisant un ET entre les sortie des portes OU et NAND, on obtient le résultat voulu. [[File:3 gate XOR.svg|centre|vignette|upright=1|Porte XOR fabriquée à partir de portes ET/OU/NON, alternative.]] : Notons que ce circuit nous donne une idée pour créer une porte NXOR : il suffit de remplacer la porte ET finale par une porte NAND. ===Les portes NAND et NOR permettent de fabriquer toutes les autres portes=== Dans la section précédente, nous avons vu que toutes les portes logiques peuvent être créés soit uniquement à partir de portes ET/NAND , soit uniquement à partir de portes OU/NOR. Cependant, supposons que je conserve les portes ET/NAND : dois-je conserver la porte ET ou la porte NAND ? Les deux solutions ne sont pas équivalentes, car l'une permet de se passer de porte NON et pas l'autre ! Pour comprendre pourquoi, nous allons essayer de créer toutes les portes à une entrée à partir de portes ET/OU/NAND/NOR. Il est possible de créer une porte OUI en utilisant une porte ET ou encore une porte OU, comme illustré ci-dessous. La raison est que si on fait un ET/OU entre un bit et lui-même, on retrouve le bit initial. Il s'agit d'une propriété particulière de ces portes, sur laquelle nous reviendrons rapidement dans le chapitre sur les circuits combinatoires, et qui sera très utile vers la fin du chapitre. Par contre, impossible de créer une porte NON facilement. {| |[[File:Buffer from OR.svg|centre|vignette|Porte Buffer faite à partir d'un OU.]] |[[File:Buffer from AND.svg|centre|vignette|Porte Buffer faite à partir d'un ET.]] |} Maintenant, que se passe-t-il si on utilise une porte NAND/NOR ? La réponse est simple : on obtient une porte NON ! Pour comprendre pourquoi, il faut imaginer que la porte NAND/NOR est composée d'une porte ET/OU suivie par une porte NON. Le bit d'entrée subit un ET/OU avec lui-même, avant d'être inversé. Le passage dans le ET/OU se comporte comme une porte OUI, alors que la porte NON l'inverse. {|class="wikitable" |+ Porte NON fabriquée avec des portes NAND/NOR |- ! ! Circuit équivalent avec des NAND ! Circuit équivalent avec des NOR |- ! Porte NON | class="transparent" | [[File:NOT from NAND.svg|centre|NOT from NAND]] | class="transparent" | [[File:NOT from NOR.svg|centre|NOT from NOR]] |} : Vous vous demandez peut-être ce qu'il se passe quand on fait la même chose avec une porte XOR, en faisant un XOR entre un bit et lui-même. Et bien le résultat est une porte FALSE. En effet, la porte XOR fournit un zéro quand les deux bits d'entrée sont identiques, ce qui est le cas quand on XOR un bit avec lui-même. Et inversement, une porte TRUE peut se fabriquer en utilisant une porte NXOR. Il s'agit là d'une propriété particulière de la porte XOR/NXOR sur laquelle nous reviendrons rapidement dans le chapitre sur les circuits combinatoires, et qui sera très utile dans le chapitre sur les opérations bit à bit. Créer les autres portes logiques est alors un jeu d'enfant avec ce qu'on a appris dans les sections précédentes. Il suffit de remplacer les portes NON et ET par leurs équivalents fabriqués avec des NAND. {|class="wikitable" |- ! ! Circuit équivalent avec des NAND ! Circuit équivalent avec des NOR |- ! Porte ET | class="transparent" | [[File:AND from NAND.svg|class=transparent|centre|AND from NAND]] | class="transparent" | [[File:AND from NOR.svg|class=transparent|centre|AND from NOR]] |- ! Porte OU | class="transparent" | [[File:OR from NAND.svg|class=transparent|centre|OR from NAND]] | class="transparent" | [[File:OR from NOR.svg|class=transparent|centre|OR from NOR]] |- ! Porte NOR | class="transparent" | [[File:NOR from NAND.svg|class=transparent|centre|NOR from NAND]] | |- ! Porte NAND | | class="transparent" | [[File:NAND from NOR.svg|class=transparent|centre|NAND from NOR]] |- ! rowspan="2" | Porte XOR | class="transparent" | [[File:XOR from NAND.svg|class=transparent|centre|300px|XOR from NAND]] | class="transparent" | [[File:XOR from NOR.svg|class=transparent|centre|300px|XOR from NOR]] |- | class="transparent" | [[File:XOR from NAND 2.svg|class=transparent|centre|300px|XOR from NAND]] | class="transparent" | [[File:XOR from NOR 2.svg|class=transparent|centre|300px|XOR from NOR]] |- ! rowspan="2" | Porte NXOR | class="transparent" | [[File:XNOR from NAND.svg|class=transparent|centre|300px|NXOR from NAND]] | class="transparent" | [[File:XNOR from NOR.svg|class=transparent|centre|300px|NXOR from NOR]] |- | class="transparent" | [[File:XNOR from NAND 2.svg|class=transparent|centre|300px|NXOR from NAND]] | class="transparent" | [[File:XNOR from NOR 2.svg|class=transparent|centre|300px|NXOR from NOR]] |} On vient de voir qu'il est possible de fabriquer tout circuit avec seulement un type de porte logique : soit on construit le circuit avec uniquement des NAND, soit avec uniquement des NOR. Pour donner un exemple, sachez que les ordinateurs chargés du pilotage et de la navigation des missions Appollo étaient intégralement conçus avec des portes NOR. ==Les portes logiques à plus de deux entrées== Par abus de langage, le terme "porte logique" désigne toutes les portes logiques à une ou deux entrées, mais pas au-delà. À l'exception de certains circuits assez simples, qui sont considérés comme des portes logiques même s'ils ont plus de deux entrées. En fait, une porte logique est un circuit simple, qui sert de brique de base pour d'autres circuits. En clair, les portes logiques sont des circuits élémentaires, et sont aux circuits électroniques ce que les atomes sont aux molécules. Dans ce qui suit, nous allons voir des portes logiques qui ont plus de 2 entrées. Beaucoup de ces circuits sont très utiles et reviendront régulièrement dans la suite du cours. ===Les portes ET/OU/NAND/NOR à plusieurs entrées=== Les premières portes logiques à plusieurs entrées que nous allons voir sont les portes ET/OU/NAND/NOR à plus de 2 entrées. Il existe des portes ET qui ont plus de deux entrées. Elles peuvent en avoir 3, 4, 5, 6, 7, etc. Comme pour une porte ET normale, leur sortie ne vaut 1 que si toutes les entrées valent 1 : dans le cas contraire, la sortie de la porte ET vaut 0. Dit autrement, si une seule entrée vaut 0, la sortie de la porte ET vaut 0. {| |[[File:3-Input AND ANSI.svg|vignette|Porte ET à trois entrées, symbole ANSI]] |[[File:MFrey AND with 3 Inputs 002.svg|vignette|Porte ET à trois entrées, symbole CEI]] |} De même, il existe des portes OU/NOR à plus de deux entrées. Pour les portes OU à plusieurs entrées, leur sortie est à 1 quand au moins une de ses entrées vaut 1. Une autre manière de le dire est que leur sortie est à 0 si et seulement si toutes les entrées sont à 0. {| |[[File:3ИЛИ.jpg|vignette|Porte OU à trois entrées, symbole CEI]] |[[File:3-Oder-Gatter-Schaltsymbol-DIN40700.png|vignette|Porte OU à trois entrées, symbole DIN]] |} Les versions NAND et NOR existent elles aussiet leur sortie/comportement est l'inverse de celle d'une porte ET/OU à plusieurs entrées. Pour les portes NAND, leur sortie ne vaut 1 que si au moins une entrée est nulle : dans le cas contraire, la sortie de la porte NAND vaut 0. Dit autrement, si toutes les entrées sont à 1, la sortie vaut 0. {| |[[File:3И-НЕ.jpg|vignette|Porte NOR à trois entrées, symbole CEI]] |[[File:3ИЛИ-НЕ.jpg|vignette|Porte NAND à trois entrées, symbole CEI]] |} Bien sur, ces portes logiques peuvent se créer en combinant plusieurs portes ET/OU/NOR/NAND à deux entrées. Cependant, faire ainsi n'est pas la seule solution et nous verrons dans le chapitre suivant que l'on peut faire nettement mieux avec quelques transistors. Elles sont très utiles dans la conception de circuits électroniques, mais elles sont aussi fortement utiles au niveau pédagogique. Nous en ferons un grand usage dans la suite du cours, car elles permettent de simplifier fortement les schémas et les explications pour certains circuits complexes. Sans elles, certains circuits seraient plus compliqués à comprendre, certains schémas seraient trop chargés en portes ET/OU pour être lisibles. ===La porte à majorité=== La '''porte à majorité''' est une porte à plusieurs entrées, qui met sa sortie à 1 quand une plus de la moitié des entrées sont à 1, et sort un 0 sinon. En général, le nombre d'entrée de cette porte est impair, pour éviter une situation où exactement la moitié des entrées sont à 1 et l'autre à 0. Il existe cependant des portes logiques à 4, 6, 8 entrées, mais elles sont plus rares. Une porte à majorité est souvent fabriquée à partir de portes logiques simples (ET, OU, NON, NAND, NOR). Mais on considère que c'est une porte logique car c'est un circuit simple et utile. De plus, il est possible de créer une grande partie des circuits électroniques possibles en utilisant seulement des portes à majorité ! Voici le circuit d'une porte à majorité à trois entrées : [[File:Majority Logic.png|centre|vignette|upright=1.5|Porte à majorité à trois bits d'entrée.]] Voici le circuit d'une porte à majorité à 4 bits d'entrées : [[File:Four-Bit Majority Circuit.png|centre|vignette|upright=1.5|Porte à majorité à quatre bits d'entrée.]] Les deux circuits précédents nous disent comment fabriquer une porte à majorité générale. Pour la porte à trois entrée, on prend toutes les paires d'entrées possibles, on fait un ET entre les bits de chaque paire, puis on fait un OU entre le résultat des ET. Pareil pour la porte à 4 entrées : on prend toutes les combinaisons de trois entrées possibles, on fait un ET par combinaison, et on fait un OU entre tout le reste. Pour une porte à 5 entrées, on devrait utiliser là encore les combinaisons de trois entrées possibles. En fait, la recette générale est la suivante : pour une porte à N entrées, on toutes les combinaisons de (N+1)/2 entrées, on fait un ET par combinaison, puis on fait un OU entre les résultats des ET. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les codes de détection/correction d'erreur | prevText=Les codes de détection/correction d'erreur | next=Les circuits combinatoires | nextText=Les circuits combinatoires }} {{autocat}} </noinclude> 35n9luiejmu64lwbggzxsdlq0e3a14u Python pour le calcul scientifique/Éléments de programmation 0 72883 768398 767923 2026-06-23T12:21:13Z Cdang 1202 /* Substitution de variables */ - , 768398 wikitext text/x-wiki Rappel : les programmes commencent par : <syntaxhighlight lang="python"> #!/usr/bin/python3 import numpy as np import matplotlib.pyplot as plt </syntaxhighlight> == Entrées et sorties == Pour permettre à l'utilisateur ou à l'utilisatrice d'entrer une valeur, nous utilisons la fonction <code lang="python">input()</code> comme évoqué précédemment (chapitre ''[[../Premiers programmes|Premiers programmes]]''), avec la syntaxe <code lang="python">''variable'' = input(''texte'')</code>. Notez que la valeur renvoyée par <code lang="python">input()</code> est une chaîne de caractères. Si vous voulez autre chose, typiquement un nombre, il faut convertir cette chaîne. Par exemple, nous demandons ici d'entrer une longueur sous la forme d'une valeur numérique : <syntaxhighlight lang="python"> longueurDefaut = 10.0 texteDemandeLongueur = f"Veuillez entrer la longueur en millimètres (valeur par défaut {longueurDefaut} mm) : " longueur = input(texteDemandeLongueur) if longueur=="": longueur=longueurDefaut else: longueur=float(longueur) print(longueur) </syntaxhighlight> {{voir|https://docs.python.org/3/library/functions.html#input}} Pour afficher un texte, on utilise la fonction <code lang="python">print()</code>, également présentée dans le chapitre ''[[../Premiers programmes|Premiers programmes]]'', avec la syntaxe <code lang="python">print(''texte'')</code>. Le texte à afficher peut être de n'importe quel type (entier, réel en virgule flottante, booléen, chaîne de caractères…). On peut « mélanger » les types en les séparant par des virgules, par exemple <syntaxhighlight lang="python"> print("La longueur vaut : ", longueur, " mm.") </syntaxhighlight> ou bien <syntaxhighlight lang="python"> print("Essai de mélange ", 1, True, 10.0, " insensé.") </syntaxhighlight> Mais si l'on veut faire ça de manière harmonieuse, on a intérêt à tout convertir en chaînes de caractères, avec la fonction <code lang="python">str()</code>, et concaténer les chaînes avec <code lang="python">+</code>. Par exemple : <syntaxhighlight lang="python"> print("La longueur vaut : "+str(longueur)+" mm.") </syntaxhighlight> Nous pouvons aussi utiliser une « chaîne “f” » ''({{lang|en|f-string}})'' : on met un le <code lang="python">f</code> devant le guillemet ouvrant et dans la chaîne, on met un champ sous la forme <code lang="python">{''nomDeVariable''}</code>. L'exemple ci-dessus devient alors : <syntaxhighlight lang="python"> print(f"La longueur vaut : {longueur} mm.") </syntaxhighlight> Les chaînes « f » sont détaillées dans la section ''[[#Chaînes de caractères|Chaînes de caractères]]'' ci-dessous. Si l'on veut introduire un retour à la ligne dans la chaîne, on utilise les caractères <code lang="python">\n</code> (contre-oblique suivie de la lettre N minuscule). Par exemple <syntaxhighlight lang="python"> print("Ceci est un texte\navec un retour à la ligne.") </syntaxhighlight> La commande <code>print()</code> admet les paramètres suivants (nous indiquons la valeur par défaut= : * <code>end = "\n"</code> : détermine la fin de ligne ; on peut mettre <code>end = ""</code> si l'on ne veut pas de retour de ligne, ou bien <code>end = "\r"</code> ''({{lang|en|return}})'' si l'on veut revenir au début de la ligne pou repasser par-dessus ; * <code>sep = " "</code> : séparateur des différents objets. {{voir|https://docs.python.org/3/library/functions.html#print}} Si vous voulez passer un argument directement au script Python, vous pouvez utiliser le module <code>sys</code>. L'argument est alors contenu dans la variable <code>sys.argv[1]</code> ; la variable <code>sys.argv[0]</code> contient le nom du scirpt lui-même. Par exemple <syntaxhighlight lang="python"> import sys print("Script : ", sys.argv[0]) print("Entrée : ", sys.argv[1]) </syntaxhighlight> Si vous exécutez le script depuis une console (fenêtre de commande), le nom du fichier de script étant <code>monscript.py</code> : <syntaxhighlight lang="text"> $ python monscript.py blabla Script : monscript.py Entrée : blabla $_ </syntaxhighlight> == Types de variables == === Généralités === Python définit « tout seul » le type de la variable : « <code>3</code> » sera un entier ''({{lang|en|integer}})'', « <code>3.0</code> » sera un réel à virgule flottante ''({{lang|en|float}})'', « <code>"3"</code> » sera une chaîne de caractères ''({{lang|en|string}})''. On peut connaître le type d'une variable avec la fonction <code>type()</code>. On peut tester certaines valeurs, avec le module <code>NumPy</code> : * <code>np.isnan(x)</code> indique si les valeurs de ''x'' sont des NaN ''({{lang|en|not a number}})'' ; si ''x'' est une matrice, le résultat est une matrice de booléens, l'élément [''i'', ''j''] est <code>True</code> si <code>x[i, j]</code> est un NaN ; * <code>np.isinf(x)</code> indique si les valeurs de ''x'' sont ±∞ ; si ''x'' est une matrice, le résultat est une matrice booléenne de même dimension. On peut forcer un type : * <code>int(x)</code> : transforme la valeur ''x'' en nombre entier ; * <code>long(x)</code> : " en entier long (précision illimitée) ; * <code>float(x)</code> : " en nombre réel à virgule flottante ; * <code>str(x)</code> : " en chaîne de caractères ; * <code>complex(Re, Im)</code> : crée le nombre complexe ''Re'' + ''Im''·j, j désignant la racine carrée de –1 ; * <code>list()</code> : crée une liste ; * <code>tuple()</code> : crée un n-uplet. Par exemple <syntaxhighlight lang="python"> type(3) # <class 'int'> type(float(3)) # <class 'float'> complex(1, 1) == 1 + 1j # True list("blabla") # ['b', 'l', 'a', 'b', 'l', 'a'] </syntaxhighlight> Python distingue plusieurs genres de types : * Un itérable est un objet dont on peut extraire les éléments un par un ; ce sont les objets pour lesquels on peut écrire <code> for i in ''iterable'':</code>. Il s'agit essentiellement des listes, n-uplets, chaînes de caractères, ensembles, dictionnaires et fichiers. * Un modifiable ''({{lang|en|mutable}})'' est un objet que l'on peut modifier ; par exemple une liste est modifiable — on peut changer la valeur d'un élément, en ajouter ou en enlever un — mais les n-uplets non, pas plus qu'une chaîne de caractères ou un nombre. * Un identifiable (''{{lang|en|hashable}}'', le ''{{lang|en|hashage}}'' étant une signature caractéristique d'un objet) : objet possédant un identifiant unique. Un objet identifiable est toujours non-modifiable ''({{lang|en|unmutable}})''. === Types numériques === ==== Entiers ==== Nous pouvons définir les entiers au format octal ou hexadécimal : il faut débuter le nombre par respectivement <code>0o</code> (le chiffre zéro et la lettre o) et <code>0x</code> (le chiffre zéro et la lettre x). À l'inverse, la fonction <code>hex()</code> renvoie une chaîne correspondant à l'écriture d'un entier au format hexadécimal, et <code>oct()</code> renvoie la chaîne correspondant à l'éciture en octal. Par exemple : <syntaxhighlight lang="python"> print(0o10, ";", 0x10) # 8 ; 16 print(hex(20)) # 0x14 </syntaxhighlight> ==== Réels ==== Les réels disposent de fonctions spécifiques appelées « méthodes ». Une méthode est une fonction spécifique à un type d'objets. Étant conçue ''ad hoc'', elle est souvent plus économe en ressource et en temps qu'une fonction générique. Pour appliquer la méthode <code>meth()</code> à la variable <code>x</code>, on écrit : <code>x.meth()</code>. Nous avons déjà présenté la méthode <code>''float''.as_integer_ratio()</code> qui donne la fraction réduite égale à la valeur du nombre. Les réels disposent de plusieurs autres méthodes : * <code>''float''.is_integer()</code> : indique si le nombre est un entier (<code>true</code> dans ce cas-là, <code>False</code> sinon) ; * <code>''float''.from_number(''x'')</code> : transforme le nombre ''x'' en un réel (permet de convertir un entier en réel) ; * <code>''float''.hex()</code> : renvoie une chaîne de caractères correspondant à l'écriture du nombre en hexadécimal ; * <code>''float''.fromhex(''c'')</code> : transforme une chaîne de caractères, correspondant à l'écriture d'un nombre en hexadécimal, en un nombre réel correspondant. Par exemple : <syntaxhighlight lang="python"> a = 20. print(a.hex()) # 0x1.4000000000000p+4 print(10..hex()) # 0x1.4000000000000p+3 </syntaxhighlight> Dans le deuxième exemple, nous appliquons la méthode <code>''float''.hex()</code> directement au nombre <code>10.</code> ; le point est obligatoire car sinon, c'est un entier, pour lequel la méthode n'est pas définie. On aurait pu aussi écrire <code>print(10.0.hex())</code>. Notez que la ''méthode'' <code>''float''.hex()</code> est différentes de la ''fonction'' <code>hex()</code> : la première concerne les réels, la seconde les entiers. ==== Complexes ==== Nous avons déjà mentionné la méthode <code>''complex''.conjugate()</code> qui donne le conjugué du nombre. Un nombre complexe dispose de deux attributs : * <code>''complex''.real</code> : sa partie réelle ; * <code> ''complex''.imag</code> : sa partie imaginaire. Par exemple : <syntaxhighlight lang = "python"> a = 5+2j print(a.conjugate(), ";", a.real, ";", a.imag) # (5-2j) ; 5.0 ; 2.0 </syntaxhighlight> === Chaînes de caractères === ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/inputoutput.html | titre = 7. Input and Output | site = Python Documentation | consulté le = 2019-04-06 }} : {{lien web | url = https://docs.python.org/3/library/string.html | titre = <code>string</code> — Common string operations | site = Python Documentation | consulté le = 2026-06-05 }} ==== Généralités ==== Il existe en fait trois manières de définir une chaîne de caractères : * avec des guillemets simples ou doubles comme vu précédemment : <code>"…"</code> ou bien <code>'…'</code> ; * avec trois guillemets doubles : <code>"""…"""</code> : cela permet d'avoir une chaîne de caractères s'étendant sur plusieurs lignes, les retours de ligne étant pris en compte ; c'est utilisé en particulier pour la description des fonctions (''{{lang|en|docstrings}}'', voir ci-après) ; * avec des guillemets précédés d'un « r », <code>r"…"</code> ou <code>r'…'</code> : cela permet d'interpréter les barres de fraction inverses « \ » comme un caractère « normal » et non comme un caractère d'échappement (voir ci-après) ; cela est utile lorsque l'on utilise les possibilités LaTeX dans le tracé de graphiques (voir plus loin) ; * avec des guillemets précédés d'un « f », <code>f"…"</code> ou <code>f'…'</code> : cela permet d'utiliser des variables formatées (voir ci-après). Une chaîne de caractères n'est pas modifiable. Si l'on veut remplacer un caractère, l'insérer ou le supprimer, il faut transformer la chaîne en liste, avec la commande <code>list()</code>, puis rassembler la liste en la joignant ''({{lang|en|join}})'' à une chaîne vide : <syntaxhighlight lang="python"> chaine = "blabla" chaineList = list(chaine) chaineList[2] = "c" chaine = "".join(chaineList) print(chaine) # blcbla </syntaxhighlight> Dans une chaîne simple <code>"…"</code> ou <code>'…'</code>, on peut introduire un retour à la ligne avec <code>\n</code>. Chaque caractère possède un code ''({{lang|en|code point}})'' définit par la norme Unicode ''({{lang|en|Unicode code point}})''. Pour afficher le caractère correspondant à un code, on utilise <code>chr()</code>. Pour afficher le code correspondant à un caractère, on utilise <code>ord()</code> <syntaxhighlight lang="python"> print(ord("a")) # 97 print(hex(ord("a"))) # 0x61 print(chr(97)) # a print(chr(0x61)) # a </syntaxhighlight> ==== Substitution de variables ==== Lorsque l'on veut utiliser des variables, on fait précéder les guillemets d'un « f » et l'on écrit les noms de vrariables entre accolades. Par exemple : <syntaxhighlight lang="python"> monde = "world" chaine = f"Hello {monde}!" print(chaine) # Hello world! </syntaxhighlight> On peut indiquer la taille de la chaîne générée à partir de la variable sous la forme <code>{nomVariable:taille}</code>, la taille étant un entier. Par exemple : <syntaxhighlight lang="python"> chiffre1 = 1 nom1 = "un" chiffre2 = 2 nom2 = "deux" chaine = f"{nom1:5} : {chiffre1:5d}\n{nom2:5} : {chiffre2:5d}" print(chaine) # un : 1 # deux : 2 </syntaxhighlight> Vous remarquez que l'on ajoute un « d » pour les entiers décimaux, et que les nombres sont alignés à droite. Si le nombre est un nombre réal à virgule flottante ''({{lang|en|float}})'', on peut indiquer le nombre de décimales sous la forme <code>.''n''f</code> : <syntaxhighlight lang="python"> chaine = f"{np.pi:.5f}" print(chaine) # 3.15169 </syntaxhighlight> Avec la syntaxe <code>''m''.''n''f</code>, on indique également que la totalité du nombre doit occuper ''m'' caractères. Pour un nombre en notaiton scientifique (exponentielle), on utilise <code>.''n''e</code>. Pour convertir un nombre en caractère Unicode correspondant, on utilise la lettre c : <syntaxhighlight lang="python"> nompi = 0x03c0 # Caractère Unicode π : U+03C0 chaine = f"{nompi:c} = {np.pi:.5f}" print(chaine) # π = 3.14159 </syntaxhighlight> Le tiret de soulignement « <code>_</code> » (''underscore'', tiret du 8) permet de séparer les chiffres avant le séparateur décimal par groupe de trois chiffres séparés du tiret ; la virgule « <code>,</code> » les sépare d'une virgule. <syntaxhighlight lang="python"> print(f"{1e6:_}, {1e6:,}") # 1_000_000.0, 1,000,000.0 </syntaxhighlight> La classe ''str'' dispose également de la méthode <code>.format()</code>. On indique un n-uplet de chaînes (ou de nombres) à la méthode et l'on met des accolades dans la chaîne principale ; les accolades sont remplacées dans l'ordre des chaînes de la méthode. On peut changer l'ordre en indiquant quelle valeur utiliser dans quelle accolade. Par exemple : <syntaxhighlight lang="python"> chaine1 = "On compte {} puis {}".format(1, 2) chaine2 = "On compte {0} puis {1}. Mais à rebours, on compte {1} puis {0}.".format("un", "deux") print(chaine1, "\n", chaine2) # On compte 1 puis 2 # On compte un puis deux. Mais à rebours, on compte deux puis un. </syntaxhighlight> L'utilisation du caractère pourcent « % » permet d'utiliser la mise en forme <code>sprintf()</code> du langage C : <syntaxhighlight lang="python"> chaine = "π = %.5f" % np.pi print(chaine) # π = 3.14159 </syntaxhighlight> ; Exemple <nowiki>:</nowikI> barre de progression : Voici une fonction affichant une barre de progression, pour la ''i''-ème étape d'un processus ayant ''n'' étapes (pour la notion de fonction, voir la section ci-après ''[[#Fonction|Fonction]]''). : NB : nous avons utilisé les codes Unicode pour l'exemple, mais on peut évidemment copier le caractère, par exemple depuis une table Unicode ou une page Web<ref>Pour le point médian : ''{{W|Table des caractères Unicode/U0080}}'' ou ''{{W|Point médian}}''. Pour le pavé : ''{{W|Table des caractères Unicode/U2580}}''.</ref>, et le coller dans le code, comme nous l'avons fait dans le commentaire. <syntaxhighlight lang="Python"> def barre_progression(i, n, largeur=40): """ Affiche une barre de progression Entrées : — i : étape en cours, entier ; — n : nombre d'étapes à réaliser, entier ; — largeur : nombre de caractères total de la barre, entier. Sortie : affichage de la barre de progression. """ taux = i/n fait = int(largeur * taux) barre = f"{0x2588:c}" * fait + f"{0x00b7:c}" * (largeur - fait) # U+2588 : pavé "█" ; U+00B7 : point médian "·" print(f"Progression | {barre} | {100*taux:3.1f} %", end="\r") barre_progression(25, 100) # Progression | ██████████······························ | 25.0 % </syntaxhighlight> ==== Méthodes des chaînes ==== Le type ''str'' dispose d'un certain nombre de méthodes. Nous avons déjà vu les méthodes <code>''str''.join()</code> et <code>''str''.format()</code>, en voici quelques autres : * <code>''str''.capitalize()</code> : met le premier caractère en capitale (majuscule) et les autres en minuscule ; * <code>''str''.lower()</code> : met tout en minuscules ''({{lang|en|lowercase}})'' ; * <code>''str''.upper()</code> : met tout en capitales ''({{lang|en|lowercase}})'' ; * <code>''str''.center(''n'')</code> : met la chaîne au centre d'une chaîne de longueur ''n'', en complétant avec des espaces ; on peut compléter avec d'autres caractères avec <code>''str''.center(''n'', ''c'')</code>, par exemple <code>"a".center(7, ".")</code> donne <code>"....a...."</code> ; * <code>''str''.ljust(''n'', ''c'')</code> et <code>''str''.rjust(''n'', ''c'')</code> : comme <code>.center()</code> mais la chaîne est respectivement alignée au fer à gauche ''({{lang|en|left}})'' et à droite ''({{lang|en|right}})'' ; * <code>''str''.isdigit()</code> : booléen vrai si tous les caractères sont des nombres ; * <code>''str''.find(''sous-chaine'')</code>, <code>''str''.rfind(''sous-chaine'')</code> : indique respectivement le premier emplacement et le dernier emplacement de la sous-chaîne dans la chaîne, ou bien <code>-1</code> si la sous-chaîne est absente ; * <code>''str''.partition(''séparateur'')</code> : retourne un triplet avec la portion de chaîne avant le séparateur, le séparateur puis la portion de chaîne après le séparateur ; * <code>''str''.replace(''ancien'', ''nouveau'')</code> : remplace la chaîne ''ancien'' par la chaîne ''nouveau'' dans la chaîne ; * <code>''str''.split(''séparateur'')</code> : découpe la chaîne au niveau des séparateurs et renvoie une liste. ==== Autres fonctions ==== La fonction <code>chr()</code> transforme un code Unicode en caractère. Par exemple, <code>chr(97)</code> donne <code>"a"</code> et <code>chr(0x03c0)</code> donne <code>"π"</code>. Si on veut créer une liste de caractères qui se suivent, on peut par exemple utiliser : <syntaxhighlight lang="python"> [chr(x) for x in range(97, 102)] # ['a', 'b', 'c', 'd', 'e'] </syntaxhighlight> Si on veut créer une liste de nombres sous la forme de chaînes de caractères, on peut utiliser la commande <code>str()</code> vue ci-dessus. Par exemple : <syntaxhighlight lang="python"> [str(x) for x in range(1, 6)] # ['1', '2', '3', '4', '5'] </syntaxhighlight> Pour la syntaxe, voir ci-dessous la section [[#Définition en compréhension|''Définition en compréhension'']]. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = chr(0x2588) * fait + chr(0x00b7) * (largeur - fait) # U+2588 : bloc ; U+00B7 : point médian </syntaxhighlight> Rappel : le module <code>html</code> permet d'utiliser les entités HTML : <syntaxhighlight lang="python"> import html … print(html.entities.html5["alpha;"]+html.entities.html5["middot;"]) # α· </syntaxhighlight> L'entité HTML <code>&xxx;</code> s'obtient par <code>html.entities.html5["xxx;"]</code>, donc en enlevant la perluète ; mais cela ne fonctionne pas avec les codes Unicode. Pour cela, on peut utiliser la commande <code>html.unescape()</code>. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = html.unescape("&#x2588;") * fait + html.entities.html5["middot;"] * (largeur - fait) # U+2588 : bloc ; middot : point médian </syntaxhighlight> ou bien <syntaxhighlight lang="python"> barre = barre = html.unescape("&#x2588;" * fait + "&middot;" * (largeur - fait)) # U+2588 : bloc ; middot : point médian </syntaxhighlight> La commande <code>html.unescape()</code> interprète donc une chaîne complète, par exemple <syntaxhighlight lang="python"> print(html.unescape("L'esperluette est le caractère &laquo;&nbsp;&amp;&nbsp;&raquo;.")) # L'esperluette est le caractère « & ». </syntaxhighlight> == Manipulation de listes == Les listes sont une structure de données fondamentale en Python. ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/datastructures.html | langue = en | titre = 5. Data structures | site = Python documentation | consulté le = 2019-03-16 }} === Copie d'une liste === Contrairement à d'autres types, lorsque vos écrivez <code>b = a</code> avec des listes, vous ne créez pas une copie de la variable <code>a</code>, vous créez un ''alias'' : l'objet <code>b</code> est un autre nom de l'objet <code>a</code>. En particulier, si vous modifiez <code>b</code>, vous modifiez en fait <code>a</code>. Par exemple : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a b[2] = 5 print(a, b) # [1, 2, 5, 4] [1, 2, 5, 4] </syntaxhighlight> Si l'on veut créer une copie de <code>a</code>, il faut utiliser <code>a[:]</code> ou bien <code>a.copy()</code> : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a[:] c = a.copy() b[2] = 5 c[2] = 6 print(a, b, c) # [1, 2, 3, 4] [1, 2, 5, 4] [1, 2, 6, 4] </syntaxhighlight> === Méthodes de listes === Pour modifier une liste, vous disposez des méthodes suivantes : * <code>a.append(x)</code> : ajoute l'élément <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.extend(x)</code> : ajoute la liste <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.append(i, x)</code> : aoute l'élément <code>x</code> ''avant'' l'interstice ''i'' de la liste <code>a</code> ; * <code> x = a.pop(i)</code> : enlève l'élément ''i'' de la liste <code>a</code> et le met dans la variable <code>x</code> ; <code> x = a.pop()</code> enlève le dernier élément de la liste ; * <code>a.clear()</code> : vide la liste <code>a</code> ; * <code>a.sort()</code> : trie la liste par ordre croissant ; * <code>a.sort(reverse = True)</code> : trie par ordre décroissant ; * <code>a.reverse()</code> : inverse l'ordre de <code>a</code>. Pour supprimer l'élément à l'indice ''i'', au lieu d'utiliser <code>a.pop(i)</code>, on peut aussi utiliser <syntaxhighlight lang="python"> del(a[i]) </syntaxhighlight> Pour trier une liste, on peut aussi utiliser la fonction <code>sorted()</code>, ce qui permet par exemple de conserver la liste originale, non triée : <code>b = sorted(a)</code>. La fonction <code>sorted()</code> fonctionne avec tous les objets « itérables » comme par exemple une chaîne de caractères : <syntaxhighlight lang="python"> a = "ahjbfk" print(sorted(a)) # ['a', 'b', 'f', 'h', 'j', 'k'] </syntaxhighlight> Pour mettre en évidence la performance de la méthode <code>''list''.sort()</code> par rapport à la fonction générique <code>sorted()</code> : <syntaxhighlight lang="python"> import numpy as np import time a = np.random.rand(int(1e7)) t1 = time.perf_counter() b = sorted(a) # Fonction générique t2 = time.perf_counter() a.sort() # Méthode spécifique t3 = time.perf_counter() print("Sorted :", t2-t1, " s ; .sort :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # Sorted : 14.2... s ; .sort : 1.1... s ; rapport : 12.6... </syntaxhighlight> Par rapport à une valeur donnée : * <code>a.remove(x)</code> : retire la première occurrence de la valeur <code>x</code> de la liste <code>a</code> ; * <code>a.index(x)</code> : indique l'indice où se trouve la première occurrence de la valeur <code>x</code> ; * <code>a.count(x)</code> : indique le nombre de fois que l'on trouve la valeur <code>x</code> dans la liste <code>a</code>. === Définition en compréhension === La [[w:fr:Liste en compréhension|définition en compréhension]] ''({{lang|en|list comprehension}})'' est une méthode permettant de construire des listes en indiquant simplement des axiomes, des consignes de filtrage. Cette méthode est élégante car proche de la notation mathématique et compacte, mais c'est une méthode itérative donc lente par rapport à une méthode vectorisée fournie par le module NumPy. Par exemple, pour créer la liste des carrés des nombres entiers entre 0 et 9, il suffit d'écrire <syntaxhighlight lang="python"> carre = [x**2 for x in range(10)] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x^2 | x \in [0 ; 9] \}</math>. Si l'on veut la liste des nombres strictement inférieurs à 20 dont le carré est supérieur à 10, on peut écrire : <syntaxhighlight lang="python"> X = [x for x in range(20) if x**2 > 10] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x | x \in [0 ; 19], x^2 > 10 \}</math>. Pour mettre en évidence la performance du calcul vectorisé par rapport à la méthode itérative : <syntaxhighlight lang="python"> import time import numpy as np n = int(1e7) # taille de la liste t1 = time.perf_counter() carre = [x**2 for x in range(n)] # Définition en compréhension t2 = time.perf_counter() carre2 = np.arange(n)**2 # Calcul vectorisé t3 = time.perf_counter() print("En compréhension : ", t2-t1, "s ; vectorisé :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # En compréhension : 4.515... s ; vectorisé : 0.156... s ; rapport : 28.982... </syntaxhighlight> == Structure d'un programme == Un programme est simplement une suite d'instructions. Dans les environnements Unix BSD, un programme Python peut être considéré comme un script c'est-à-dire qu'il suffit de taper son nom dans l'invite de commande ''({{lang|en|shell}})'' sans avoir à invoquer <code>python</code>. Le programme doit alors commencer par un en-tête normalisé surnommé ''{{lang|en|[[wikt:shebang|shebang]]}}'' : <syntaxhighlight lang="python"> #!/usr/bin/env python3 </syntaxhighlight> Ce ''{{lang|en|shebang}}'' est inutile avec Jupyter. L'en-tête peut également contenir la description de l'encodage du fichier texte, typiquement : <syntaxhighlight lang="python"> # coding: utf-8 </syntaxhighlight> Le codage UTF-8 est le codage par défaut pour Python 3, il est donc inutile de l'indiquer. Les commentaires sont introduits par le croisillon <code>#</code>. On peut grouper une suite d'instructions dans un bloc. Un bloc d'instructions commence par deux-points « <code>:</code> » et est identé, c'est-à-dire qu'il a une marge constituée de quatre espaces — on peut aussi utiliser une tabulation mais il ne faut pas mélanger les deux méthodes ; les tabulations sont déconseillées, il vaut mieux utiliser quatre espaces<ref>{{lien web | url = https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces | titre = Tabs or Spaces? | site = Python documentation | consulté le = 2019-03-14 }}</ref>. Pour terminer le bloc, il suffit simplement de revenir en début de ligne ; contrairement à d'autres langages, il n'y a pas de commende de fin ''({{lang|en|end}})'', c'est l'indentation qui définit le bloc. : # début du bloc ''instruction 1'' ''instruction 2'' … ''dernière instruction du bloc'' ''instruction hors bloc'' Par exemple, une exécution conditionnelle <code>if</code> ou une boucle <code>for</code> exécute un bloc d'instruction. Si l'on a besoin d'un bloc d'instruction qui « ne fait rien », on utilise l'instruction <code>pass</code>. == Structures de contrôle == '''Boucle itérative''' La boucle itérative s'écrit : <syntaxhighlight lang="python"> for <variable> in <itérable>: <bloc d’instructions> </syntaxhighlight> Si l'on veut que la variable prenne ''n'' valeurs de 0 à ''n'' – 1, on utilise l'instruction <code>range()</code> : <syntaxhighlight lang="python"> for i in range(5): print(i) print("Fin de la boucle") </syntaxhighlight> <code>[▶]</code> 0 1 2 3 4 Fin de la boucle En fait, la commande <code>range()</code> extrait des valeurs de l'ensemble des nombres entiers ; on peut ainsi utiliser le découpage en tranches, par exemple <code>range(2, 5)</code>pour avoir la « liste » <code>[2, 3, 4]</code>. Notez que <code>range()</code> ne crée pas à proprement parler une liste, cela crée un objet de type ''« {{lang|en|range}} »'' (plage, intervalle) ; pour avoir une liste, il faut écrire <code>list(range(n))</code>. Dans une boucle, la commande <code>continue()</code> saute la fin du bloc d'instruction et passe à la valeur suivante de la boucle. La commande <code>break()</code> interrompt la boucle et passe à la suite. '''Exécution conditionnelle''' L'exécution conditionnelle s'écrit : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> </syntaxhighlight> On peut utiliser les commandes <code>elif</code> ''(else if'') et <code>else</code> : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> elif <booléen>: <bloc d’instructions> else: <bloc d’instructions> </syntaxhighlight> Notez que le test d'une condition est gourmand en ressources. S'il s'agit de savoir si l'on effectue une opération mathématique simple ou pas, on peut remplacer le test par une multiplication par un booléen (<code>True</code> vaut 1, <code>False</code> vaut 0). Par exemple, plutôt que d'écrire <syntaxhighlight lang="python"> if a > 0: b = b - c </syntaxhighlight> mieux vaut écrire : <syntaxhighlight lang="python"> b = b - (a > 0)*c </syntaxhighlight> '''Boucle antéconditionnée''' La boucle antéconditionnée s'écrit : <syntaxhighlight lang="python"> while <booléen>: <bloc d’instructions> </syntaxhighlight> Cette boucle peut contenir des instructions <code>continue()</code> et <code>break()</code>. == Fonction == La déclaration d'une fonction utilise la commande <code>def</code>. La fonction est un bloc d'instructions. Si elle doit renvoyer des valeurs, on utilise la commande <code>return</code>. Par exemple <syntaxhighlight lang="python"> def nombres(n): """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo a = nombres(3) print(a) </syntaxhighlight> La fonction commence par une chaîne de caractères qui la décrit. Cette chaîne peut être récupérée automatiquement par certains logiciels pour faire une documentation automatique. Si la description prend plusieurs lignes, elle commence et finit par trois double-guillemets <code>"""…"""</code> ; en fait, par convention, même si cela n'est pas obligatoire, les descriptions sont toutes encadrées de trois double-guillemets. Cette description est appelée ''{{lang|en|docstring (documentation string)}}''. Pour récupérer les ''{{lang|en|docstrings}}'' : <syntaxhighlight lang="python"> def foo(): """Cette fonction ne fait rien""" pass print(foo.__doc__) # Cette fonction ne fait rien </syntaxhighlight> L'instruction <code>input()</code> permet à l'utilisateur de saisir une valeur. La valeur est retournée sous la forme d'une chaîne de caractères qui est ensuite convertie en nombre réel avec l'instruction <code>float()</code>. On peut définir une valeur par défaut en l'indiquant dans l'en-tête de la définition de la fonction, de la manière suivante : <syntaxhighlight lang="python"> def nombres(n=1): # valeur par défaut : 1 """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo </syntaxhighlight> Si le paramètre à initialiser est de type modifiable ''({{lang|en|mutable}})'', comme par exemple une liste, il faut procéder comme suit : <syntaxhighlight lang="python"> def fooFonction(fooListe=None): # valeur par défaut : n'existe pas """Description""" if fooListe = None: fooListe = [] # initialisation <suite des instructions> </syntaxhighlight> Par défaut, les variables sont locales. On peut rendre une variable globale avec l'instruction <code>global</code> ''à l'intérieur de la fonction'', avant l'utilisation de la variable. Par exemple : <syntaxhighlight lang="python"> a = 1 b = 1 def toto(): """Test de variable globale. Entrée : aucune. Sortie : aucune.""" global a a = 2 b = 2 toto() print("a =", a, "; b =", b) # a = 2 ; b = 1 </syntaxhighlight> Pour être plus précis : si une variable n'est pas assignée dans une fonction, alors Python va chercher une variable du même nom à l'extérieur de la fonction. Mais à partir du moment où la variable est assignée dans la fonction, elle devient locale ''sauf'' si l'on a utilisé l'instruction <code>global</code>. Si l'on s'attend à un nombre indéfini d'arguments, on utilise la notion d'empaquetage/dépaquetage ''({{lang|en|packing/unpacking}})''<ref>{{lien web | url = https://deusyss.developpez.com/tutoriels/Python/args_kwargs/ | titre = Introduction à *args et **kwargs | consulté le = 2019-03-09 | site = Developpez.com }}.</ref>. L'empaquetage consiste à mettre les arguments dans un n-uplet, le dépaquetage consiste à développer un n-uplet en plusieurs variables. Cela se fait en mettant un astérisque ''({{lang|en|splat}})'' « <code>*</code> » devant le nom de la variable. Par convention, on utilise le nom de variable <code>*args</code> mais cela n'est pas obligatoire. <syntaxhighlight lang="python"> def concatenation(*args): """Concatène des chaînes de caractères Entrée : *args, n-uplet de chaînes de caractères. Sortie : resultat, chaîne de caractères.""" resultat = "" for i in args: resultat = resultat + i return resultat concatenation("a", "foo", "toto") # 'afoototo' </syntaxhighlight> À l'inverse, si une fonction doit recevoir plusieurs paramètres, on peut à la place lui transmettre une liste à dépaqueter : <syntaxhighlight lang="python"> def addition(a, b): """Ajoute deux nombres Entrées : — a : réel ; — b : réel. Sortie : a+b, réel""" return a+b arg = (1, 2) addition(*arg) # 3 </syntaxhighlight> On peut aussi empaqueter/dépaqueter un dictionnaire, on utilise pour cela deux astérisques « <code>**</code> ». Par convention, on utilise le nom <code>**kwargs</code> sans que cela soit obligatoire. L'instruction <code>lambda</code> permet de créer de petites fonctions ne contenant pas de boucle ni de branchement conditionnel. Cependant, si la déclaration est courte et compacte, le code n'est pas toujours facilement lisible ; l'utilisation de cette instruction n'est pas recommandée. Par exemple l'expression <syntaxhighlight lang="python"> f = lambda x: 2*x </syntaxhighlight> est la même chose que <syntaxhighlight lang="python"> def f(x): """Calcule le double. Entrée : x, réel. Sortie : 2*x, réel.""" return 2*x </syntaxhighlight> {{note|L'instruction <code>eval()</code> exécute une chaîne de caractères, c'est-à-dire traite une chaîne de caractères comme si c'étaient des instructions données à Python. Cette instruction est à éviter pour deux raisons : # Un utilisateur malveillant pourrait entrer du code malveillant dans la chaîne de caractères. # L'exécution est lente puisque Python doit compiler la chaîne à la volée. Cette instruction peut en général être remplacée par une autre instruction. }} == Gestion des erreurs == Dans un bloc d'instructions, on peut utiliser la structure <code>try:… except:</code>. Le bloc après <code>try</code> est exécuté ; si une erreur se déclare dans ce bloc, alors le bloc <code>except</code> s'exécute. Par exemple <syntaxhighlight lang="python"> try: 1/0 # Génère une erreur except: print("Division par zéro") # Cette instruction est donc exécutée </syntaxhighlight> On peut compléter avec <code>else:</code> et <code>finally:</code> : <syntaxhighlight lang="python"> try: <code à exécuter> except: <s’exécute en cas d’erreur> else: <s’exécute s’il n’y a pas d’erreur> finally: <s’exécute dans tous les cas> </syntaxhighlight> On peut séparer les différents types d'erreur : <syntaxhighlight lang="python"> try: <code à exécuter> except ValueError: print("Valeur erronée") except TypeError: print("Type erroné") </syntaxhighlight> Les types d'erreur les plus courants sont : * <code>NameError</code> : le nom de variable n'existe pas ; * <code>TypeError</code> : la valeur n'est pas du bon type ; * <code>ValueError</code> : la valeur n'est pas compatible avec ce qui est attendu ; * <code>RuntimeError</code> : type d'erreur général. On peut aussi créer ses propres erreurs : si une situation erronée survient, on peut « lever » une exception avec <code>raise</code>. Par exemple <syntaxhighlight lang="python"> if a < 0: raise ValueError("La valeur doit être positive") </syntaxhighlight> ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/errors.html | titre = Errors and exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} * {{lien web | url = https://docs.python.org/3/library/exceptions.html | titre = Built-in Exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} == Exercices == === Calcul du PGCD et du PPCM par l'algorithme d'Euclide === {{loupe|w:Algorithme d'Euclide}} Écrire un programme Python qui demande deux nombres entiers et affiche leurs PGCD et PPCM. Le programme utilisera l'algorithme d'Euclide. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """Programme : euclide.py Auteur : User:cdang date : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : calcule le PGCD et le PPCM de deux nombres entiers. Entrée ------ au clavier, saisie de deux nombres entiers. Sorties ------- à l'écran, affichage du PGCD et du PPCM. """ # *************** # *************** # ** Fonctions ** # *************** # *************** def euclide(): """Calcule le PGCD et le PPCM avec l'algorithme d'Elclide Entrée ------ Aucune, la saisie des paramètres fait partie de la fonction Sortie ------ affichage du PGCD et du PPCM """ print("***** Algorithme d'Euclide *****\n") a0 = int(input("Premier nombre entier : a = ")) b0 = int(input("Second nombre entier : b = ")) a = a0 b = b0 r = a%b # initialisation while (r != 0) : # algorithme d'Euclide a = b b = r r = a%b # affichage des résultats print("PGCD(", a0, ", ", b0, ") = ", b) print("PPCM(", a0, ", ", b0, ") = ", a0*b0//b) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* euclide() </syntaxhighlight> On peut simplifier la boucle centrale : <syntaxhighlight lang="python"> while b: # s'exécute tant que b n'est pas 0 a, b = b, a % b # affectation de liste à liste return a </syntaxhighlight> {{boîte déroulante fin}} Notez que le module NumPy propose l'instruction <code>gcd()</code> : <syntaxhighlight lang="python"> import numpy … print(numpy.gcd(a, b)) </syntaxhighlight> === Tours de Hanoï === {{loupe|w:Tours de Hanoï}} Écrire un programme Python qui demande le nombre ''n'' de plateaux et affiche les manipulations nécessaires pour déplacer la pile d'un emplacement à un autre. Le programme utilisera l'algorithme récursif. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """nom : hanoi.py auteur : User:cdang date de création : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : résout le problème des tours de Hanoï Entrées ------- trois chaînes de caractères (nom des piliers) Sorties ------- une chaîne de caractères (liste des opérations) """ # *************** # *************** # ** Fonctions ** # *************** # *************** def hanoi(a, b, c, n): """Résout le problème des tours de Hanoï de manière récursive But : déplace la pile de n disques du piler a au pilier b Entrées ------- a, b c : chaînes de 1 caractère, référence des emplacements ; n : entier, nombre de disques sur l'emplacement a Sorties ------- operations : chaînes de caractères décrivant les opérations """" if n>1: operations = hanoi(a, c, b, n-1) operations = operations+a+"→"+b+" ; " operations = operations+hanoi(c, b, a, n-1) else: operations = a+"→"+b+" ; " return operations # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* resultat = hanoi("1", "2", "3", 3) print(resultat) </syntaxhighlight> {{boîte déroulante fin}} === Lancer de rayons === [[Fichier:Lentille hemispherique perspective.svg|vignette|Lentille hémisphérique.]] Considérons une lentille hémisphérique de rayon R faite d’un verre d’indice de réfraction ''n''. Nous plaçons une source ponctuelle à une distance ''d'' du dioptre plan, sur l’axe optique. Tracer des rayons partant de la source et traversant la lentille. {{clear}} {{Boîte déroulante/début |titre=Analyse d’optique géométrique}} [[Fichier:Lentille hemispherique analyse geometrique.svg|vignette|Analyse géométrique du problème.]] Il s’agit d’un problème ayant une symétrie de révolution par rapport à l’axe optique. Nous pouvons nous réduire à un problème plan en nous plaçant dans un plan contenant l’axe optique ; l’axe optique est encore un axe de symétrie orthogonale, nous pouvons donc nous contenter d'étudier un demi-plan. Pour simplifier, nous plaçons le centre du dioptre sphérique à l’origine O du repère. L’axe optique est l’axe ''x'' et l'axe perpendiculaire, vertical sur la figure, c’est l’axe ''y''. Les coordonnées de la source sont donc (-''d'' ; 0). Le rayon issu de la source et faisant un angle θ avec l’axe ''x'' frappe le dioptre plan à l’altitude ''h''. Nous avons : : ''h'' = ''d'' ⋅ tan θ. L’angle d’incidence vaut θ. D’après la loi de Snell-Descartes, l'angle de réfraction θ<sub>2</sub> vaut : : θ<sub>2</sub> = arcsin((sin θ) / ''n''). Le rayon réfracté passe par le points de coordonnées (0, ''h''). L’équation de la droite est donc : : ''y'' = a ⋅ ''x'' + ''h'' avec : ''a'' = tan θ<sub>2</sub>. L’équation du cercle de centre O et de rayon R est : : ''x''<sup>2</sup> + ''y''<sup>2</sup> = R<sup>2</sup>. Les coordonnées (''x''<sub>M</sub>, ''y''<sub>M</sub>) de l’intersection M du rayon avec le dioptre sphérique vérifient les deux équations. Par substitution, nous obtenons une équation du second degré en ''x'' que nous savons résoudre : : ''x''<sub>M</sub><sup>2</sup> + (''a'' ⋅ ''x''<sub>M</sub> + ''h'')<sup>2</sup> = R<sup>2</sup> : ⇔ (1 + ''a''<sup>2</sup>) ⋅ ''x''<sub>M</sub><sup>2</sup> + 2 ⋅ ''a'' ⋅ ''h'' ⋅ ''x''<sub>M</sub> + ''h''<sup>2</sup> – R<sup>2</sup> = 0. D’après les propriétés du cercle, le rayon est perpendiculaire à la tangente. Le rayon [OM] est donc normal au dioptre en M. Nous pouvons déterminer l’angle d’incidence θ<sub>i</sub> par le produit scalaire : : <math>\begin{pmatrix} 1 \\ a \end{pmatrix} \cdot \begin{pmatrix} x_\mathrm{M} \\ y_\mathrm{M} \end{pmatrix} = \sqrt{1^2 + a^2} \cdot \mathrm{R} \cdot \cos(\theta_\mathrm{i})</math> ce qui nous permet de calculer cet angle : : <math>\theta_\mathrm{i} = \operatorname{arcos} \left ( \frac{x_\mathrm{M} + a \cdot y_\mathrm{M}}{\mathrm{R} \cdot \sqrt{1^2 + a^2} } \right )</math> Comme nous passons vers un milieu d’indice plus faible, il y a un risque de réflexion totale. L’angle limite est : : θ<sub>max</sub> = arcsin(1/''n''). Si l’on a θ<sub>i</sub> &gt; θ<sub>max</sub>, le rayon repart vers l’intérieur. Nous ne traçons pas le rayon car cela nous emmènerait trop loin dans l’analyse. En revanche, si θ<sub>i</sub> ≤ θ<sub>max</sub>, alors nous pouvons appliquer la loi de Snell-Descartes pour avoir l’angle de réfraction θ<sub>e</sub> : : θ<sub>e</sub> = arcsin(''n'' ⋅ sin θ<sub>i</sub>). Pour tracer le rayon sortant, il nous faut l’angle θ<sub>3</sub> par rapport à l’horizontale. L’angle du rayon [OM] par rapport à l’horizontal vaut arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>), nous avons donc : θ<sub>3</sub> = arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>) + θ<sub>e</sub>. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Analyse algorithmique}} '''Structure des données''' Le problème est décrit par trois paramètres : # Le rayon <code>R1</code> de la lentille, en milliètres (réel en virgule flottante). # L’indice du verre, <code>n</code> sans dimension (réel en virgule flottante). L’indice de l’air vaut 1. # La distance de la source au dioptre d’entrée plan, <code>d</code> en millimètres (réel en virgule flottante). Un rayon est caractérisé par quatre paramètres : # L’angle d’émission <code>theta1</code> en radians (réel en virgule flottante). # L’angle de réfraction dans la lentille <code>theta2</code> en radians (réel en virgule flottante). # Les cordonnées <code>M</code> en millimètre (vecteur de dimension 2 <code>([x, y])</code> de réels en virgule flottante) du point d’intersection du rayon avec le dioptre sphérique. # L’angle de réfraction dans l’air après la lentille <code>theta3</code> en radians (réel en virgule flottante). Pour le calcul et le tracé, nous avons besoin des paramètres intermédiaires suivants : * l’altitude ''y'' = <code>h</code> en millimètres (réel en virgule flottante) à laquelle le rayon frappe le dioptre plan d’entrée ; * l’angle d’incidence du rayon avec le dioptre sphérique <code>thetaint</code> en radians (réel en virgule flottante). Les angles sont stockés en radians car c’est l’unité naturelle pour le calcul mais nous affichons les valeurs en degrés. Comme le calcul de conversion est récurrent, nous conservons les facteurs <code>degversrad</code> (conversion des degrés vers les radians, facteur valant π/180, réel en virgule flottante) et <code>radversdeg</code> (conversion des radians vers les degrés, facteur valant 180/π, réel en virgule flottante). '''Fonctions''' Nous avons besoin d’une fonction qui calcule les trois paramètres du rayon <code>(theta2, M, theta3)</code> à partir de l’angle d’émission <code>theta1</code>. Nous appelons cette fonction <code>lanceRayon()</code>. Cette fonction fait appelle à une fonction qui calcule l’angle du rayon réfracté à partir de l’angle du rayon incident <code>theta1</code>, les deux angles étant par rapport à la normale au dioptre au point considéré. Nous appelons cette fonction <code>refrac()</code>. La recherche de l’intersection <code>M</code> du rayon avec le dioptre sphérique nécessite de résoudre une équation du second degré. Nous utilisons pour cela la recherche des racines du polynôme en <code>x</code> avec la fonction <code lang="python">numpy.polynomial.polynomial.polyroots()</code>. D’après la configuration du problème géométrique, si l’on s’assure que le rayon frappe bien la lentille (0 ≤ <code>h</code> ≤ <code>R1</code>) alors nous sommes sûrs que le problème a deux solutions réelles (une positive et une négative) ou, dans le cas dégénéré où <code>h == R1</code>, une valeur unique <code>x == 0</code>. Comme nous recherchons la valeur positive, nous sélectionons la plus grande des deux racines. Pour la gestion de la réflexion interne : dans la fonction <code>refrac()</code>, nous vérifions les conditions de réflexion totale et si elles sont remplies, alors nous générons une erreur (commandes <code lang="python">try… except</code> et <code lang="python">raise ValueError</code>). Cette erreur est propagée à la fonction <code>lanceRayon()</code> : <code>lanceRayon()</code> appelle la fonction <code>refrac()</code> et si cette fonction renvoie une erreur, alors <code>lanceRayon()</code> renvoie également une erreur. Pour trouver l’angle d’émission <code>thetaLimite</code> provoquant la réflexion totale (en radians, réel en virgule flottante), nous effectuons une recherche par dichotomie : * nous partons de l’angle maximum possible, lorsque le rayon frappe le sommet de la lentille, et nous appelons la fonction <code>lanceRayon()</code> ; si cela ne génère pas d’erreur, alors nous pouvons aller jusqu’à cette valeur, la recherche est terminée ; si cela génère une erreur, alors nous divisons la valeur par deux ; * à une étape de la recherche donnée, si <code>lanceRayon()</code> ne génère pas d’erreur avec l’angle testé, alors nous savons que l’angle limite est supérieur à cette valeur ; cette valeur minore donc la valeur recherchée ; si au contraire <code>lanceRayon()</code> génère une erreur, alors c’est que l’angle est trop important, cette valeur majore donc la valeur recherchée ; nous pouvons ainsi resserer l’intervalle de recherche ; * nous nous arrêtons lorsque les valeurs haute et basse sont suffisamment proche. Concrètement : # Nous définissons une variable <code>angleHaut</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus bas connu provoquant la réflexion totale. # Nous définissons une variable <code>angleBas</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus haut connu ne provoquant pas de réflexion totale. Sa valeur initiale est 0. L’angle limite recherché est donc entre <code>angleBas</code> et <code>angleHaut</code>. # Nous définissons l’angle <code>angleTest</code> comme étant la moyenne entre <code>angleBas</code> et <code>angleHaut</code>. Si <code>lanceRayon(angleTest)</code> génère une erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleHaut</code> (puisque c’est une valeur provoquant la réflexion totale et qu’elle est plus basse que la valeur actuelle d’<code>angleHaut</code>). À l’inverse, si <code>lanceRayon(angleTest)</code> ne génère pas d’erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleBas</code> (puisque c’est une valeur ne provoquant pas la réflexion totale et qu’elle est plus haute que la valeur actuelle d’<code>angleBas</code>). # Nous arrêtons la procédure lorsque l’écart entre <code>angleBas</code> et <code>angleHaut</code> est inférieur à {{unité|10|échelle=<sup>–3</sup>|rad}} (valeur arbitraire). La valeur retenue est la valeur finale d’<code>angleBas</code> (puisque l’on veut être sûr qu’il n’y ait pas de réflexion totale). La valeur affichée est la valeur en degrés arrondie au dixième. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Solution}} Nous demandons à l’utilisateur ou à l’utilisatrice les valeurs des paramètres du problème : rayon de la lentille, distance de la source, indice de réfraction du verre. Nous vérifions que les valeurs entrées sont bien des nombres ; si c’est une chaîne vide, alors nous utilisons une valeur par défaut. Nous créons une fonction <code>refrac()</code> qui permet de calculer l’angle réfracté à partir de l’angle d’incidence et des indices de réfraction. S’il y a rélexion totale, alors nous générons une erreur. La fonction <code>lanceRayon()</code> calcule les différents points de passage du rayon. Elle appelle pour cela la fonction <code>refrac()</code>. Si un appel de la commande <code>refrac()</code> génère une erreur, alors nous générons également une erreur. Nous déterminons l’angle d’émision du rayon <code>thetaLimite</code> qui provoque une réflecxion totale. Pour cela, nous créons une fonction <code>rechercheLimite()</code> qui cherche par dichotomie. Nous traçons un rayon tous les 5° jusqu’à la valeur limite. <syntaxhighlight lang="python"> #!/usr/bin/env python3 # coding: utf-8 """nom : lancerRayons.py auteur : User:cdang date de création : 2022-05-06 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : NumPy, matplotlib ---------------------------------------------------------------------------- Objectif : trace des trajets optique avec une lentille hémisphérique Entrées ------- Le rayon de la lentille, la distance de la source, l’indice de réfraction du verre, trois chaînes de caractères saisies par l’utilisateur·rice et qui sont converties en réels. Sorties ------- La valeur limite de l’angle (réel) et le tracé de plusieurs rayons. """ # ****************************************************** # ****************************************************** # ** Lancer de rayons pour une lentille hémisphérique ** # ****************************************************** # ****************************************************** import numpy as np import matplotlib.pyplot as plt import numpy.polynomial.polynomial as nppol # ************** # * Constantes * # ************** # Pour la conversion degrés ↔ radians radversdeg = 180/np.pi degversrad = 1/radversdeg # ************* # * Fonctions * # ************* def boucleEntreeNombre(messageSaisie, valeurDefaut): """Permet de s’assurer que l’utilisateur·rice a bien entré un nombre. Entrée : — message à afficher (chaîne de caractères) ; — valeur par défaut (réel à virgule flottante). Sortie : nombre (réel à virgule flottante).""" messageErreur = "Veuillez entrer une valeur numérique (ou vide pour accepter la valeur par défaut).\n" execute = True while execute: strNombre = input(messageSaisie+f" (valeur par défaut {valeurDefaut}) : ") if strNombre == "": nombre = valeurDefaut execute = False else: try: nombre = float(strNombre) except: print(messageErreur) else: execute = False return nombre def initialisation(): """L’utilisateur·rice entre les variables du problème. Entrées : aucune. Sorties : — R1 (mm) : rayon de la lentille ; — d (mm) : distance de la source au dioptre plan ; — n (sans dimension) : indice de réfraction du verre.""" R1 = boucleEntreeNombre("Rayon de la lentille en mm", 20.0) d = boucleEntreeNombre("Distance de la source au dioptre plan en mm", 20.0) n = boucleEntreeNombre("Indice de réfraction (sans dimension)", 1.5) return (R1, d, n) def refrac(n1, n2, theta1): """Calcule l’angle de réfraction theta2 (radians) en fonction — de l’angle d’incidence theta1 (radians); — de l’indice de réfraction n1 du premier milieu ; — de l’indice de réfraction n2 du second milieu.""" reflexionTotale=False rapport=n2/n1 rapportinv=np.reciprocal(rapport) if n1 > n2: thetal = np.arcsin(rapport) # angle limite pour la réflexion totale if theta1 >= thetal: reflexionTotale=True if reflexionTotale: print("Réflexion totale") raise ValueError else: return np.arcsin(rapportinv*np.sin(theta1)) def lanceRayon(n1, n2, d, R, theta1): """Détermine le rayon issu de la source située à une distance d (mm) du bareau et avec une élévation de theta1 (radians), en fonction des indices de réfraction n1 et n2. Les éléments retournés sont : — la hauteur h (mm) à laquelle le rayon frappe le barreau ; — l’angle de réfraction theta2 (radians)) dans le barreau ; — l’angle de réfraction theta3 (radians) à la sortie du barreau — le point M(x, y) (mm) auquel le rayon sort du barreau.""" h = d*np.tan(theta1) if h >= R: print("Le rayon est au-dessus du barreau") raise ValueError else: theta2 = refrac(n1, n2, theta1) a = np.tan(theta2) x = max(nppol.polyroots([h*h - R*R, 2*a*h, 1+a*a])) # recherche de l’intersection du rayon avec le cercle y = a*x + h M = np.array([x, y]) thetaint = np.arccos((x + a*y)/(R*np.sqrt(1 + a*a))) theta3 = np.arctan(y/x) - refrac(n2, n1, thetaint) return (h, theta2, theta3, M) def rechercheLimite(n1, n2, d, R): """Recherche l’angle limite pour la réflexion totale. Entrée : — indice de réfraction des milieux 1 et 2, n1 et n2 ; — distance au barreau, d(mm). Sortie : angle limite theta (radians)""" angleHaut = np.arctan(R/d) angleBas = 0 angleTest = angleHaut try: lanceRayon(n1, n2, d, angleTest, R) except: condition = True # il y a réflexion total en haut de la lentille else: condition = False # il n’y a jamais réflexion totale dans la lentille while condition: #dichotomie angleTest = np.mean([angleHaut, angleBas]) # on ajuste la valeur de test try: lanceRayon(n1, n2, d, R, angleTest) except: angleHaut = angleTest # réflexion totale : on abaisse la valeur maximale else: angleBas = angleTest # pas de réflexion totale : on monte la valeur minimale condition = ((angleHaut - angleBas) >= 0.001) # on a cerné la limite à 0,001 rad près if not condition: angleTest = angleBas return angleTest # *********************** # * Programme principal * # *********************** (R1, d, n) = initialisation() xmax = round(R1 + d) thetaLimite = rechercheLimite(1, n, d, R1) thetaLimiteDeg = thetaLimite*radversdeg print(f"Angle limite pour la réflexion totale : {thetaLimiteDeg:.1f}°.\n") anglesDeg = np.arange(0, thetaLimiteDeg, 5)[1:] # trace un rayon tous les 5° anglesRad = anglesDeg*degversrad nb = len(anglesDeg) h = np.zeros(nb) # initialisation des vecteurs de valeurs theta2 = np.zeros(nb) theta3 = np.zeros(nb) M = np.zeros((nb, 2)) for i in range(nb): (h[i], theta2[i], theta3[i], M[i, :]) = lanceRayon(1, n, d, R1, anglesRad[i]) (h_lim, theta2_lim, theta3_lim, M_lim) = lanceRayon(1, n, d, R1, thetaLimite) # tracé anglesCercle = 0.5*np.pi*(np.linspace(1, 0, 20)) x_cercle = R1*np.cos(anglesCercle) # coordonnées des pints du cercle y_cercle = R1*np.sin(anglesCercle) fig = plt.plot([-d,xmax], [0, 0], "k-.", linewidth="0.5") # tracé de l’axe optique for i in range(nb): plt.plot([-d, 0, M[i, 0], xmax], [0, h[i], M[i, 1], M[i, 1] + (xmax - M[i, 0])*np.tan(theta3[i])], label=f"{anglesDeg[i]:.0f}°") plt.plot([-d, 0, M_lim[0], xmax], [0, h_lim, M_lim[1], M_lim[1] + (xmax - M_lim[0])*np.tan(theta3_lim)], label=f"{0.1*int(np.trunc(10*thetaLimite*radversdeg)):.1f}°") plt.plot(x_cercle, y_cercle, "k", linewidth="0.5") # tracé du cercle plt.plot([0,0], [0, R1], "k", linewidth="0.5") # tracé du premier dioptre #plt.axis("square") plt.gca().set_aspect("equal", adjustable="box") plt.xlabel("x (mm)") plt.ylabel("y (mm)") plt.title("Lentille hémisphérique, lancer de rayons") plt.legend() plt.savefig("lentille_hemispherique_lancer_rayon.svg", format="svg") plt.show() </syntaxhighlight> {{Boîte déroulante/fin}} == Mesurer le temps == Le module <code>time</code> fournit les fonctions suivantes : * <code>time.gmtime()</code> : renvoie la date et l'heure du méridien de Greenwich (''{{lang|en|Greenwich mean time}}'', GMT), sous la forme d'un dictionnaire (année, mois, jour du mois, heure, minute, seconde, jour de la semaine, jour de l'année, heure d'été/hiver), ** jour de la semaine est un entier entre 0 (lundi) et 6 (dimanche), ** jour du mois est un entier entre 1 et 366 ; * <code>time.localtime()</code> : comme le précédent, mais l'heure est l'heure locale ; * <code>time.time()</code> : donne le nombre de seconde qui se sont écoulées depuis le 1er janvier 1970 ; * <code>time.gmtime(n)</code> et <code>time.localtime(n)</code> transforment un nombre de secondes (écoulées depuis le 1er janvier 1970) en une date au format (année, mois, jour, etc.), n-uplet de neuf valeurs ; <code>time.mktime()</code> fait le contraire, il transforme un n-uplet de neuf valeurs (années, mois, jour, etc.) en un nombre de secondes (écoulées depuis le 1er janvier 1970) ; * <code>time.sleep(n)</code> : provoque une pause dans le déroulement du programme de ''n'' secondes ; * <code>time.perf_counter()</code> : indique une date en seconde ; s'utilise pour mesurer la durée d'exécution d'une partie du code, en faisant la différence entre deux relevés. Concernant la date et l'heure sous la forme d'un n-uplet, on peut extraire l'heure de la manière suivante : <syntaxhighlight lang="python"> import time a = time.localtime() print("Il est ", a[3], "h", a[4]) # ou bien print("Il est ", a.tm_hour, "h", a.tm_min) </syntaxhighlight> Pour mesurer la performance d'une portion de code : <syntaxhighlight lang="python"> import time t1 = time.perf_counter() <suite d’instructions> t2 = time.perf_counter() print("Durée d'exécution :", t2-t1 </syntaxhighlight> == Programmation orientée objet == Nous n'allons pas ici faire un cours de programmation orientée objet (POO), nous allons aborder le sujet de manière pragmatique. De manière schématique, un « objet » est une « super-variable ». Cette super-variable peut contenir plusieurs variables, appelées « attributs » ; elle contient en fait un dictionnaire (paires « nom d'attribut : valeur d'attribut »). Elle peut aussi contenir des fonctions spécifiques appelées « méthodes ». De même qu'une variable a un type, un objet fait partie d'une « classe ». La classe est le modèle de l'objet ; en franglais informatique, on dit que l'objet est une instance de la classe. La POO est donc un formalisme : lorsque l'on définit des variables et des fonctions concernant un même type d'objet (au sens commun du terme), on les empaquette dans une classe. Il faut donc d'abord définir la classe, puis attribuer cette classe à un objet (« instancier » la classe). Considérons par exemple que nous voulons travailler sur des [[w:Engrenage|engrenages]] ; pour simplifier, nous nous contentons d'engrenages à dentures droites. Une roue dentée, un pignon, est essentiellement définie par son nombre de dents Z et par son module ''m'' qui correspond à la largeur de dents<ref>ainsi que par son épaisseur ''e'' et le matériau dont elle est faite mais nous allons négliger ces paramètres pour la simplicité de l'étude.</ref>. Nous allons définir trois méthodes : la méthode <code>.diametrePrimitif()</code> qui calcule le diamètre primitif de la roue dentée, <code>.pas()</code> qui calcule la largeur des dents au niveau du cercle primitif et <code>.rapport()</code> qui calcule le rapport de transmission de deux roues engrenées Z<sub>1</sub>/Z<sub>2</sub>. La méthode <code>.rapport()</code> vérifie par ailleurs que les roues ont le même module, condition indispensable pour former un engrenage. Nous définissons la classe ainsi : <syntaxhighlight lang="python"> class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): # instructions lancées lors de la déclaration """Valeurs des attributs""" self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z </syntaxhighlight> Nous remarquons que lorsque nous déclarons les méthodes, le paramètre <code>self</code> correspond à l'objet lui-même. Ainsi, dans la méthode <code>.rapport()</code>, la variable <code>self.Z</code> est le nombre de dents de la roue elle-même et <code>roueDentee.Z</code> est le nombre de dents de la roue passée en paramètre. Pour déclarer les roues, nous écrivons : <syntaxhighlight lang="python"> roue1 = pignon() # attribution de la classe, « instanciation » roue1.Z = 13 # définition des caractéristiques du pignon « roue1 » roue1.m = 2 roue2 = pignon(16, 2) # manière alternative </syntaxhighlight> Nous pouvons alors utiliser les objets de la manière suivante : <syntaxhighlight lang="python"> print(roue1.Z) # 13 print(roue1.diametrePrimitif()) # 26 R = roue1.rapport(roue2) # 0.8125 </syntaxhighlight> La commande <code>dir(a)</code> affiche tous les attributs et méthodes de l'objet <code>a</code>. ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/classes.html | titre = Classes | site = Python documentation | consulté le = 2019-03-08 }} == Interface graphique avec Tk == === Généralités === Une interface graphique utilisateur (GUI, ''{{lang|en|graphic user interface}}'') est un ensemble de boîtes permettant d'interagir avec l'utilisateur, c'est-à-dire qui permettent la saisie d'informations, l'exécution d'actions et l'affichage d'informations. L'interface se compose d'éléments appelés ''{{lang|en|widgets}}''. Les éléments ''({{lang|en|widgets}})'' classiques sont : * boîte de dialogue ''({{lang|en|dialog box}})'' : fenêtre contenant d'autres éléments ; * étiquette ''({{lang|en|label}})'' : texte affiché ; * liste déroulante ''({{lang|en|drop-down list}})'' : zone permettant le choix d'une option, la liste se déployant lorsque l'on clique sur la zone ; * zone de texte, champ de saisie ''({{lang|en|text box}})'' : zone permettant de taper du texte ; * boîte combinée ''({{lang|en|combo box}})'' : zone de saisie de texte contenant une liste déroulante qui permet de choisir des éléments prédéfinis ; * bouton ''({{lang|en|button}})'' : objet effectuant une action lorsque l'on clique dessus ; * case à cocher ''({{lang|en|checkbox, tickbox}})'' : objet permettant d'activer ou de désactiver une option lorsque l'on clique dessus ; * bouton radio, case d'option ''({{lang|en|radio button}})'' : objet permettant d'activer une option en désactivant les autres options ; une seule option peut être activée à la fois. === Avec Tk === Plusieurs modules permettent de gérer les interfaces graphiques. Nous choisissons ici le module développé sur la bibliothèque Tk qui est une bibliothèque multiplateforme. Pour cela, nous importons le module <code>tkinter</code> ainsi que le module <code>ttk</code>, ce dernier proposant des options plus « modernes » : <syntaxhighlight lang="python"> import tkinter as tk from tkinter import ttk </syntaxhighlight> Voici un programme permettant comme précédemment de calculer le rapport de transmission d'un engrenage. Nous détaillons sa construction ci-après. <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: IUrapport.set(valeurZ2/valeurZ1) except: IUrapport.set("erreur") # ************************* # ************************* # ** Interface graphique ** # ************************* # ************************* # fenetre principale fenetre = tk.Tk() fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> [[Fichier:Organisation interface Tk Python.svg|vignette|upright=2|Organisation des ''widgets''.]] '''Explications''' Nous commençons par définir la boîte de dialogue que nous appelons <code>fenetre</code> ; c'est un objet <code>Tk</code> et nous lui donnons un titre « » : <syntaxhighlight lang="python"> fenetre = tk.Tk() fenetre.title("Rapport de réduction") </syntaxhighlight> Puis, nous définissons un cadre attaché à cette fenêtre et qui va nous permettre « d'accrocher » les autres éléments, ce qui permet de garder une apparence satisfaisante lorsque l'on retaille la fenêtre : <syntaxhighlight lang="python"> cadre = ttk.Frame(fenetre) </syntaxhighlight> Le cadre va comporter six lignes ''({{lang|en|row}})'' et deux colonnes ''({{lang|en|column}})''. Nous allons placer une étiquette ''({{lang|en|label}})'' « z1 » : <code>text="z1"</code>. Cette étiquette se trouve dans une case du cadre, celle de la première colonne et la première ligne : <code>grid(column=1, row=1)</code>. Par rapport à cette case, elle est collée à « l'ouest » (W, ''{{lang|en|west}}'', gauche) de la case : <code>sticky=tk.W</code>. <syntaxhighlight lang="python"> z1_label = ttk.Label(cadre, text="z1") # Création de l'étiquette z1_label.grid(column=1, row=1, sticky=tk.W) # Placement de l'étiquette </syntaxhighlight> Notez que l'on aurait pu écrire directement : <syntaxhighlight lang="python"> ttk.Label(cadre, text="z1").grid(column=1, row=1, sticky=tk.W) </syntaxhighlight> mais le fait de séparer la création de l'élément et son placement facilite la maintenance (recherche d'erreur, évolution du code). Pour tout ce qui est dynamique, c'est-à-dire les zone de saisie des valeurs et l'affichage du résultat, il faut définir des « chaînes variables » ''({{lang|variable strings}})'' : <syntaxhighlight lang="python"> IUz1 = tk.StringVar() </syntaxhighlight> Cette variable est une variable globale à la création. Nous pouvons alors placer la zone de saisie ''({{lang|en|entry}})'' à côté de l'étiquette lui correspondant. Nous nommons la zone de saisie <code>z1_entry</code> : <syntaxhighlight lang="python"> z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) </syntaxhighlight> Nous faisons de même pour les trois autres paramètres de l'engrenage, ''m''<sub>1</sub>, ''z''<sub>2</sub> et ''m''<sub>2</sub>. Le résultat est également une chaîne variable globale. Par rapport à notre mise en page, elle se situe dans la case colonne 2 ligne 5, centrée sur cette case (collé à l'est et à l'ouest) : <syntaxhighlight lang="python"> rapport = tk.StringVar() rapport_dynamique = ttk.Label(cadre, textvariable=rapport) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) </syntaxhighlight> Il nous faut encore définir une fonction de manière classique, nous l'appelons « calcule ». Les variables étant globales, on les utilise directement. On récupère les valeurs avec la méthode <code>get()</code> et nous modifions la valeur avec la méthode <code>set()</code> : <syntaxhighlight lang="python"> def calcule(): valeurZ1 = float(IUz1.get()) valeurZ2 = float(IUz2.get()) IUrapport.set(valeurZ2/valeurZ1) </syntaxhighlight> Cette fonction est déclenchée lorsque l'on clique sur le bouton « Calcul » situé dans la case du cadre ligne 6 colonne 2 : <syntaxhighlight lang="python"> bouton = ttk.Button(cadre, text="Calcul", command=calcule) bouton.grid(column=2, row=6, sticky=tk.W) </syntaxhighlight> ou bien si l'on appuie sur la touche <code>[entrée]</code> du clavier : <syntaxhighlight lang="python"> fenetre.bind("<Return>", calcule) </syntaxhighlight> À tout ceci, nous ajoutons des « gouttières » (marges, ''{{lang|en|paddings}}'') afin d'espacer les éléments. Il faut ensuite « activer » la fenêtre pour qu'elle s'affiche. La méthode est <code>mainloop()</code> (boucle principale) : « boucle » (elle est active en permanence et attend des actions sur ses éléments), <syntaxhighlight lang="python"> fenetre.mainloop() </syntaxhighlight> Nous avons ci-dessus mis la plupart du code en programme principal. Nous pouvons aussi programmer de manière fonctionnelle, en mettant la plupart du code dans des fonctions ; cependant, pour que la fenêtre et les variables dynamiques soient globales à tout le programme, elles doivent être déclarées dans le programme principal. Nous pouvons aussi mêler la programmation orientée objet. {{boîte déroulante début|Calcul du rapport de transmission en programmation fonctionnelle et orientée objet}} <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # ************* # ************* # ** Classes ** # ************* # ************* class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): """Valeurs des attributs""" # instructions lancées lors de la déclaration self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z # ************************ # ************************ # ** Variables globales ** # ************************ # ************************ # fenetre principale fenetre = tk.Tk() # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: roue1 = pignon(valeurZ1, valeurM1) roue2 = pignon(valeurZ2, valeurM2) IUrapport.set(roue1.rapport(roue2)) except: IUrapport.set("Erreur") # *********************** # * Interface graphique * # *********************** def configureFenetre(): """Configuration de la fenêtre principale""" fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* configureFenetre() # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> {{boîte déroulante fin}} {{voir |{{lien web |url=https://docs.python.org/3/library/tkinter.ttk.html |titre=tkinter.ttk — Tk themed widgets |site=docs.python.org |consulté le=2026-06-11}} }} {{voir |{{lien web |url=https://matplotlib.org/stable/gallery/user_interfaces/embedding_in_tk_sgskip.html |titre=How to embed Matplotlib charts in Tkinter GUI? |site=Matplotlib.org |date=2025-07-15 |consulté le=2026-06-11}} }} === Avec PyQt === Le module PyQt (prononcer \ˈpaɪ.kjut\) permet d'utiliser la bibliothèque Qt dévelopée par Riverbank Computing. Il permet notamment de créer des interfaces graphiques. La communication entre objets Qt se fait par une mécanismes de « signal/emplacement » ''({{lang|en|signal/slot}})''. Un emplacement ''({{lang|en|slot}})'' est une fonction ''({{lang|en|callable}})'' ; un signal est un attribut d'un objet. Si l'attribut signal est défini pour l'emplacement, alors on dit que l'emplacement est relié à un signal. Par exemple, un objet <code>QPushButton</code> dispose du signal <code>clicked</code> qui est émis lorsque l'on clique dessus ; on peut ainsi faire exécuter un emplacement (fonction appelable) <code>action()</code> lorsque l'on clique sur le bouton par le biais du signal <code>clicked</code> : <syntaxhighlight lang="python"> from PyQt5.QtWidgets import QPushButton bouton = QPushButton("Appuies-moi dessus") button.clicked.connect(action()) </syntaxhighlight> {{voir|{{lien web |url=https://www.riverbankcomputing.com/static/Docs/PyQt6/ |titre=Reference guide PyQt6 |site=Riverbank Computing|consulté le=2026-0604}} }} {{...}} == Annotations == Une annotation est un commentaire qui sert à expliciter un type de variable. La syntaxe est différente des commentaires « classiques » : cela permet d'avoir un affichage différent avec les éditeurs de texte ayant une coloration syntaxique, et ces informations peuvent être récupérées par des logiciels extérieurs pour effectuer une documentation automatique ou bien des vérifications de type. Cependant : * comme les commentaires normaux, ils n'ont aucune influence lors de l'exécution du texte ; en particulier : * rien n'oblige à annoter les variables ; * il est possible d'avoir une variable ayant un type différent de son annotation ; le fait de pouvoir définir et changer le type de variable à la volée est une fonctionnalité fondamentale de Python. La syntaxe pour une annotation est : : nom_de_variable + deux-points + espace + type par exemple : <syntaxhighlight lang="python"> a: int </syntaxhighlight> Notez qu'ici, la variable n'est ''pas'' créée. Pour la créer, il faut lui affecter une valeur. Il est possible de l'affecter après ou bien sur la même ligne avec la syntaxe : : nom_de_variable + deux-points + espace + type + espace + égal + espace + valeur par exemple : <syntaxhighlight lang="python"> a: int a = 5 # est équivalent à a: int = 5 </syntaxhighlight> Même si l'annotation n'a pas d'impact sur l'exécution, le type doit être un type existant sinon cela génère une erreur de syntaxe. Les types classiques sont : : <code>int</code> — <code>float</code> — <code>str</code> — <code>bool</code> — <code>list</code> — <code>tuple</code> — <code>dict</code> Il est également possible de mettre une chaîne de caractères : <syntaxhighlight lang="python"> a: "ce que je veux" = 3.1516 </syntaxhighlight> On peut annoter une fonction. Il est possible d'annoter les variables déclarées au sein de la fonction, mais pas les variables globales (puisqu'elle ne sont pas définie au sein de la fonction). On peut aussi annoter : * les variables passées en paramètre, avec la même syntaxe dans les parenthèses ; * annoter le type de la variable de sortie (retournée) en la faisant précéder de <code>-&gt;</code> : <syntaxhighlight lang="python"> def plusCinq(a: float = 0) -> float: return a + 5 </syntaxhighlight> ; Ressources * {{lien web | url = https://www.python.org/dev/peps/pep-0526/ | titre = PEP 526 -- Syntax for Variable Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} * {{lien web | url = https://www.python.org/dev/peps/pep-3107/ | titre = PEP 3107 -- Function Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} == Décorateur == Un décorateur est une fonction qui s'applique à une fonction, à la manière de la composition mathématique ''g'' ∘ ƒ = ''g''(ƒ). Mais cette composition affecte la fonction elle-même ; l'utilisateur appelle la fonction ƒ mais c'est la fonction ''g'' ∘ ƒ qui s'exécute. Cette fonction ''g'' est appelée le décorateur. L'intérêt est de pouvoir modifier une fonction sans modifier le code de la fonction elle-même. Pour appliquer une décoration, il faut : # Déclarer le décorateur : une fonction qui s'applique à une autre fonction. # Affecter le décorateur à la fonction visée : en mettant <code>@''décoration''</code> juste avant la définition de la fonction. Par exemple : <syntaxhighlight lang="python"> def decorateur(f): print("Avant la fonction") f() print("après la fonction") @decorateur def afficheFoo(): print("Foo.") afficheFoo # Avant la fonction # Foo. # Après la fonction </syntaxhighlight> Lorsque l'on appelle <code>afficheFoo</code>, on appelle en fait <code>decorateur(afficheFoo)</code>. Si la fonction à modifier admet des paramètres, il faut définir une fonction enveloppante dans le décorateur. Par exemple, nous définissons ci-dessous un décorateur <code>deuxFois()</code> qui fait s'exécuter deux fois de suite la fonction : <syntaxhighlight lang="python"> def deuxFois(f): def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # conteneurFonction </syntaxhighlight> Nous voyons que l'application du décorateur a modifié le nom de la fonction — pas le nom de la variable qui contient la fonction mais bien son nom « intime ». Pour éviter cela, on utilise la méthode <code>wraps()</code> du module <code>functools</code> : <syntaxhighlight lang="python"> import functools def deuxFois(f): @functools.wraps(f) def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # plusCinq </syntaxhighlight> On peut par exemple utiliser un décorateur pour la mémoïsation. La mémoïsation est une méthode consistant à mémoriser les valeurs d'une fonction au fur et à mesure de son utilisation ; ainsi, si l'on veut évaluer la fonction avec les mêmes entrées, on se contente d'aller chercher la valeur enregistrée ce qui est plus rapide. On sacrifie donc la place mémoire au profit de la rapidité. On peut trouver des décorateurs de mémoïsation aux adresses suivantes : * https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize * https://gist.github.com/robcowie/1357800 ; Ressources : {{lien web | url = https://www.python.org/dev/peps/pep-0318/ | titre = PEP 318 -- Decorators for Functions and Methods | site = Python.org | lang = en | consulté le = 2019-04-05 }} == Manipulation de fichiers == === Importer le contenu d'un fichier === Python possède la fonction <code lang="python">open()</code> qui permet d'ouvrir un fichier. Ouvrir signifie qu'il crée un objet de type <code>file</code> qui possède notamment les méthodes <code lang="python">.read()</code> et <code lang="python">.write()</code>. Il peut s'agir d'un objet de type « fichier binaire » ''({{lang|en|binary file}})'' ou « fichier texte » ''({{lang|en|text file}})''. Si par exemple on veut utiliser (et donc lire) le contenu du fichier texte <code>monfichier.txt</code>, on écrit : <syntaxhighlight lang="python"> fichier = open("monfichier.txt", "rt") … fichier.close() </syntaxhighlight> Le paramètre <code>"rt"</code> signifie que nous ouvrons le fichier en lecture ''({{lang|en|read}})'' et qu'il s'agit d'un objet de type fichier texte. Notons deux choses : * en faisant cela, nous ne faisons qu'associer le fichier à un objet Python, nous n'avons pas encore importé les données ; * si nous ouvrons le fichier, il faut le fermer par la suite ; c'est pourquoi nous utilisons la méthode <code lang="python">.close()</code>. Pour éviter d'avoir à fermer le fichier, nous pouvons l'ouvrir au sein d'un contexte : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: … </syntaxhighlight> Notons aussi que la chaîne de caractères indiquant le nom du fichier peut contenir le chemin d'accès au répertoire (dossier), mais sous Microsoft Windows, il faut utiliser des barres de fractions <code>/</code> pour séparer les sous-répertoires au lieu de la barre inversée habituelle, par exemple : <syntaxhighlight lang="python"> chemin = "C:/Temp/monfichier.txt" with open(chemin, "rt") as fichier: … </syntaxhighlight> Pour mettre les données du fichier dans la variable <code>contenu</code>, nous écrivons donc : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() print(contenu) </syntaxhighlight> et si nous ne voulons lire que les <code>n</code> premiers caractères (<code>n</code> étant un entier), nous utilisons <code lang="python">contenu = fichier.read(n)</code>. Cette lecture est séquentielle, c'est-à-dire que si nous appliquons la méthode plusieurs fois, nous reprenons la lecture là où nous l'avons laissée. Si nous voulons lire une ligne, nous utilisons la méthode <code lang="python">.readline()</code>. La lecture ligne par ligne est également séquentielle. Nous pouvons aussi créer une liste dont chaque élément est une ligne du fichier ; nous utilisons alors la méthode <code lang="python">.readlines()</code> (notez le pluriel). Chaque élément de la liste se termine par le caractère de fin de ligne <code lang="python">\n</code>. Pour l'enlever, nous pouvons utiliser la méthode <code lang="python">.rstrip()</code> pour chaque élément de la liste, par exemple. L'exemple complet est alors : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.readlines() contenu = [item.rstrip() for item in contenu] print(contenu) </syntaxhighlight> === Exporter du contenu vers un fichier === Si nous voulons créer un fichier texte <code>monfichier.txt</code> pour y mettre le contenu de la variable <code>texte</code>, alors nous utilisons : <syntaxhighlight lang="python"> with open("monfichier.txt", "wt") as fichier: fichier.write(texte) </syntaxhighlight> Le module principal important pour la manipulation de fichiers est est <code lang="python">os</code>. === Exploiter le contenu d'un fichier texte === Avec un fichier texte, la méthode <code lang="python">.read()</code> crée une variable de type texte. Nous pouvons séparer cette variable en différentes lignes avec la méthode <code lang="python">.splitlines()</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une ligne. Si maintenant une ligne contient plusieurs données séparées par un séparateur commun, par exemple un espace, nous pouvons séparer les données par la méthode <code lang="python">.split(''séparateur'')</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une donnée. Si par exemple le fichier est du type CSV ''({{lang|en|comma separated values}}'', valeurs séparées par une virgule), l'exploitation du fichier est : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(",") for item in contenu] </syntaxhighlight> La variable <code>contenu</code> est une liste de listes. Pour avoir la ''n''<sup>e</sup> valeurs de la ''m''<sup>e</sup> ligne, on utilise : <syntaxhighlight lang="python"> contenu[m-1][n-1] </syntaxhighlight> Si l'on veut extraire la ligne ''m'' il suffit d'écrire : <syntaxhighlight lang="python"> contenu[m-1] </syntaxhighlight> mais si l'on veut la colonne ''n'', le plus simple est d'utiliser une définition en compréhension : <syntaxhighlight lang="python"> [ligne[n-1] for ligne in contenu] </syntaxhighlight> Dans certains fichiers CSV, les séparateurs de valeurs ne sont pas des virgules, on peut donc utiliser un autre caractère pour le séparateur. Concernant les séparateurs particuliers : * si le séparateur est une tabulation, on utilise <code lang="python">\t</code> : <code lang="python">contenu = [item.split("\t") for item in contenu]</code> ; * si le séparateur est un nombre arbitraire d'espaces et/ou de tabulation, on ne définit aucun séparateur : <code lang="python">contenu = [item.split() for item in contenu]</code>. Si la première ligne contient les en-têtes des colonnes, on peut l'enlever avec la fonction <code lang="python">del()</code> : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() del(contenu[0]) contenu = [item.split(",") for item in contenu] </syntaxhighlight> Certains logiciels créent des fichiers en utilisant le séparateur décimal régional, qui en France est la virgule. Pour remplacer les virgules par des points, on peut utiliser la méthode <code lang="python">.replace()</code>, de préférence ''avant'' de séparer les valeurs : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.replace(",", ".") for item in contenu] # remplace les virgules par des points contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule </syntaxhighlight> en effet, lorsque l'on a séparé les valeurs, on a une liste de liste, il faut alors balayer les sous-listes ce qui prend plus de temps : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule contenu = [[subitem.replace(",", ".") for subitem in item] for item in contenu] # remplace les virgules par des points </syntaxhighlight> '''Exemple complet''' Supposons que l'on ait un fichier texte de la forme : <syntaxhighlight lang="text"> x y z V 0.0 1.5 3.2 8.657 0.4 1.5 3.2 8.392 0.2 1.5 3.2 8.485 ... </syntaxhighlight> C'est un fichier valeurs V associées à des points de coordonnées ''(x, y, z)'' (un champ V sur l'espace, donc). Nous remarquons que seule la coordonnée ''x'' change : les données concernent la droite (''y'' = 1,5 ; ''z'' = 3,2). Nous remarquons aussi que les valeurs de ''x'' ne sont pas classées par ordre croissant ni décroissant. Nous voulons au final avoir une matrice [[''x''], [V]] triée par ''x'' croissant. Pour cela, nous pouvons faire : <syntaxhighlight lang="python"> with open(nomdefichier, "rt") ad fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(" ") for item in contenu contenu = contenu[1:] # élimine la première ligne x = np.array([float(ligne[0]) for ligne in contenu]) V = np.array([float(ligne[3]) for ligne in contenu]) donnees = np.concatenate((x.reshape(-1, 1), V.reshape(-1, 1)), axis=1) # matrice [[x], [V]] ind = np.argsort(donnees[:, 0]) donnees = donnees[ind, :] # matrice triée plt.plot(donnees[:, 0], donnees[:, 1]) </syntaxhighlight> {{note|Pour le tri, voir [[../Manipulation_de_matrices#Fonctions_et_méthodes_de_base|''Manipulation de matrices'' &gt; ''Fonctions et méthodes de base'']].}} === Cas d'un fichier CSV === Si le fichier CSV ne contient que des valeurs numériques, on peut utiliser : <syntaxhighlight lang="python"> valeurs = np.loadtxt(chemin+nomfic, delimiter=",") # si le séparateur est une virgule </syntaxhighlight> Il existe un module <code lang="python">csv</code> dédié aux fichiers CSV. La manipulation du fichier se fait comme suit : <syntaxhighlight lang="python"> import csv with open(chemin+nomfic, "rt") as fichier: lecteur = csv.reader(fichier, delimiter=",") contenu = [ligne for ligne in lecteur] print(contenu) </syntaxhighlight> === Utilisation de Pandas === Pandas<ref>https://pandas.pydata.org/</ref> est un module gérant les tableaux de données, appelés <em lang="en">data frames</em>. Voici quelques commandes utiles : <syntaxhighlight lang="python"> import numpy as np import pandas as pd M = np.random.rand(10, 10) # crée une matrice NumPy aléatoire de dimension 10 × 10 tableau = pd.DataFrame(M) # transforme la matrice en tableau DataFrame tableau.to_csv("tableau.csv") # enregistre le tableau dans un fichier CSV donnees = pd.read_csv("tableau.csv").to_numpy() # lit le fichier et transforme le tableau DataFrame en matrice NumPy </syntaxhighlight> Par défaut, la fonction <code>pd.read_csv()</code> considère que le séparateur est une virgule, et la commande <code>pd.read_table()</code> que c'est une tabulation. On peut définir le séparateur avec le paramètre <code>sep</code> : <syntaxhighlight lang="python"> donnees = pd.read_csv("tableau.csv", sep=";") </syntaxhighlight> On peut utiliser les séparateurs spéciaux : * <code>\t</code> : tabulation ; * <code>\s+</code> : nombre arbitraire d'espaces. On peut par ailleurs utiliser les paramètres suivants : * <code>dialect</code> : syntaxe du fichier, par exemple <code>dialect = "excel"</code> ; * <code>nrows</code> (entier) : nombre de lignes lues ; * <code>skiprows</code> (entier) : nombre de lignes sautées (non lues) en début de fichier ; * <code>header</code> (entier) : numéro de ligne utilisé pour l'en-tête, par exemple <code>header = 0</code> pour la première ligne ; * <code>skip_blank_lines</code> (booléen) : si la valeur est vraie (<code>True</code>), ne lit pas les lignes vide ; sinon, met une valeur <code>nan</code>. Par exemple : <syntaxhighlight lang="python"> donnees1 = pd.read_csv("tableau.csv", nrows=1, sep="\s+").to_numpy() donnees2 = pd.read_csv("tableau.csv", skiprows=3, sep="\s+").to_numpy() </syntaxhighlight> {{voir|{{lien web |url=https://pandas.pydata.org/docs/user_guide/io.html |titre=IO tools (text, CSV, HDF5, …) |site=Pandas |consulté le=2026-05-06}} }} == Exporter un programme Python == Vous pouvez créer un fichier « Python pur » <code>.py</code>. Pour cela, dans le menu <code>fichier/file</code> de Jupyter, choisir <code>télécharger/download</code> au format <code>.py</code> ; le fichier se trouve alors dans le répertoire de téléchargement du navigateur. == Recommandations == Les recommandations de programmation sont générales et ne sont en grande partie pas spécifiques à Python. {{voir|[[Découvrir_Scilab/Programmation#Recommandations]]}} == Ressources == * {{lien web | url = https://www.python.org/dev/peps/pep-0008/ | titre = PEP 8 -- Style Guide for Python Code | site = Python documentation | consulté le = 2019-03-14 }} == Notes et références == {{références}} ---- [[../Fonctions mathématiques générales|Fonctions mathématiques générales]] &lt; [[../|↑]] &gt; [[../Graphiques|Graphiques]] {{DEFAULTSORT:Elements de programmation}} [[Catégorie:Python pour le calcul scientifique (livre)]] g00et5makrbwj47ykuvovyeuunak5l1 768399 768398 2026-06-23T12:22:59Z Cdang 1202 /* Substitution de variables */ voc : f-string 768399 wikitext text/x-wiki Rappel : les programmes commencent par : <syntaxhighlight lang="python"> #!/usr/bin/python3 import numpy as np import matplotlib.pyplot as plt </syntaxhighlight> == Entrées et sorties == Pour permettre à l'utilisateur ou à l'utilisatrice d'entrer une valeur, nous utilisons la fonction <code lang="python">input()</code> comme évoqué précédemment (chapitre ''[[../Premiers programmes|Premiers programmes]]''), avec la syntaxe <code lang="python">''variable'' = input(''texte'')</code>. Notez que la valeur renvoyée par <code lang="python">input()</code> est une chaîne de caractères. Si vous voulez autre chose, typiquement un nombre, il faut convertir cette chaîne. Par exemple, nous demandons ici d'entrer une longueur sous la forme d'une valeur numérique : <syntaxhighlight lang="python"> longueurDefaut = 10.0 texteDemandeLongueur = f"Veuillez entrer la longueur en millimètres (valeur par défaut {longueurDefaut} mm) : " longueur = input(texteDemandeLongueur) if longueur=="": longueur=longueurDefaut else: longueur=float(longueur) print(longueur) </syntaxhighlight> {{voir|https://docs.python.org/3/library/functions.html#input}} Pour afficher un texte, on utilise la fonction <code lang="python">print()</code>, également présentée dans le chapitre ''[[../Premiers programmes|Premiers programmes]]'', avec la syntaxe <code lang="python">print(''texte'')</code>. Le texte à afficher peut être de n'importe quel type (entier, réel en virgule flottante, booléen, chaîne de caractères…). On peut « mélanger » les types en les séparant par des virgules, par exemple <syntaxhighlight lang="python"> print("La longueur vaut : ", longueur, " mm.") </syntaxhighlight> ou bien <syntaxhighlight lang="python"> print("Essai de mélange ", 1, True, 10.0, " insensé.") </syntaxhighlight> Mais si l'on veut faire ça de manière harmonieuse, on a intérêt à tout convertir en chaînes de caractères, avec la fonction <code lang="python">str()</code>, et concaténer les chaînes avec <code lang="python">+</code>. Par exemple : <syntaxhighlight lang="python"> print("La longueur vaut : "+str(longueur)+" mm.") </syntaxhighlight> Nous pouvons aussi utiliser une « chaîne “f” » ''({{lang|en|f-string}})'' : on met un le <code lang="python">f</code> devant le guillemet ouvrant et dans la chaîne, on met un champ sous la forme <code lang="python">{''nomDeVariable''}</code>. L'exemple ci-dessus devient alors : <syntaxhighlight lang="python"> print(f"La longueur vaut : {longueur} mm.") </syntaxhighlight> Les chaînes « f » sont détaillées dans la section ''[[#Chaînes de caractères|Chaînes de caractères]]'' ci-dessous. Si l'on veut introduire un retour à la ligne dans la chaîne, on utilise les caractères <code lang="python">\n</code> (contre-oblique suivie de la lettre N minuscule). Par exemple <syntaxhighlight lang="python"> print("Ceci est un texte\navec un retour à la ligne.") </syntaxhighlight> La commande <code>print()</code> admet les paramètres suivants (nous indiquons la valeur par défaut= : * <code>end = "\n"</code> : détermine la fin de ligne ; on peut mettre <code>end = ""</code> si l'on ne veut pas de retour de ligne, ou bien <code>end = "\r"</code> ''({{lang|en|return}})'' si l'on veut revenir au début de la ligne pou repasser par-dessus ; * <code>sep = " "</code> : séparateur des différents objets. {{voir|https://docs.python.org/3/library/functions.html#print}} Si vous voulez passer un argument directement au script Python, vous pouvez utiliser le module <code>sys</code>. L'argument est alors contenu dans la variable <code>sys.argv[1]</code> ; la variable <code>sys.argv[0]</code> contient le nom du scirpt lui-même. Par exemple <syntaxhighlight lang="python"> import sys print("Script : ", sys.argv[0]) print("Entrée : ", sys.argv[1]) </syntaxhighlight> Si vous exécutez le script depuis une console (fenêtre de commande), le nom du fichier de script étant <code>monscript.py</code> : <syntaxhighlight lang="text"> $ python monscript.py blabla Script : monscript.py Entrée : blabla $_ </syntaxhighlight> == Types de variables == === Généralités === Python définit « tout seul » le type de la variable : « <code>3</code> » sera un entier ''({{lang|en|integer}})'', « <code>3.0</code> » sera un réel à virgule flottante ''({{lang|en|float}})'', « <code>"3"</code> » sera une chaîne de caractères ''({{lang|en|string}})''. On peut connaître le type d'une variable avec la fonction <code>type()</code>. On peut tester certaines valeurs, avec le module <code>NumPy</code> : * <code>np.isnan(x)</code> indique si les valeurs de ''x'' sont des NaN ''({{lang|en|not a number}})'' ; si ''x'' est une matrice, le résultat est une matrice de booléens, l'élément [''i'', ''j''] est <code>True</code> si <code>x[i, j]</code> est un NaN ; * <code>np.isinf(x)</code> indique si les valeurs de ''x'' sont ±∞ ; si ''x'' est une matrice, le résultat est une matrice booléenne de même dimension. On peut forcer un type : * <code>int(x)</code> : transforme la valeur ''x'' en nombre entier ; * <code>long(x)</code> : " en entier long (précision illimitée) ; * <code>float(x)</code> : " en nombre réel à virgule flottante ; * <code>str(x)</code> : " en chaîne de caractères ; * <code>complex(Re, Im)</code> : crée le nombre complexe ''Re'' + ''Im''·j, j désignant la racine carrée de –1 ; * <code>list()</code> : crée une liste ; * <code>tuple()</code> : crée un n-uplet. Par exemple <syntaxhighlight lang="python"> type(3) # <class 'int'> type(float(3)) # <class 'float'> complex(1, 1) == 1 + 1j # True list("blabla") # ['b', 'l', 'a', 'b', 'l', 'a'] </syntaxhighlight> Python distingue plusieurs genres de types : * Un itérable est un objet dont on peut extraire les éléments un par un ; ce sont les objets pour lesquels on peut écrire <code> for i in ''iterable'':</code>. Il s'agit essentiellement des listes, n-uplets, chaînes de caractères, ensembles, dictionnaires et fichiers. * Un modifiable ''({{lang|en|mutable}})'' est un objet que l'on peut modifier ; par exemple une liste est modifiable — on peut changer la valeur d'un élément, en ajouter ou en enlever un — mais les n-uplets non, pas plus qu'une chaîne de caractères ou un nombre. * Un identifiable (''{{lang|en|hashable}}'', le ''{{lang|en|hashage}}'' étant une signature caractéristique d'un objet) : objet possédant un identifiant unique. Un objet identifiable est toujours non-modifiable ''({{lang|en|unmutable}})''. === Types numériques === ==== Entiers ==== Nous pouvons définir les entiers au format octal ou hexadécimal : il faut débuter le nombre par respectivement <code>0o</code> (le chiffre zéro et la lettre o) et <code>0x</code> (le chiffre zéro et la lettre x). À l'inverse, la fonction <code>hex()</code> renvoie une chaîne correspondant à l'écriture d'un entier au format hexadécimal, et <code>oct()</code> renvoie la chaîne correspondant à l'éciture en octal. Par exemple : <syntaxhighlight lang="python"> print(0o10, ";", 0x10) # 8 ; 16 print(hex(20)) # 0x14 </syntaxhighlight> ==== Réels ==== Les réels disposent de fonctions spécifiques appelées « méthodes ». Une méthode est une fonction spécifique à un type d'objets. Étant conçue ''ad hoc'', elle est souvent plus économe en ressource et en temps qu'une fonction générique. Pour appliquer la méthode <code>meth()</code> à la variable <code>x</code>, on écrit : <code>x.meth()</code>. Nous avons déjà présenté la méthode <code>''float''.as_integer_ratio()</code> qui donne la fraction réduite égale à la valeur du nombre. Les réels disposent de plusieurs autres méthodes : * <code>''float''.is_integer()</code> : indique si le nombre est un entier (<code>true</code> dans ce cas-là, <code>False</code> sinon) ; * <code>''float''.from_number(''x'')</code> : transforme le nombre ''x'' en un réel (permet de convertir un entier en réel) ; * <code>''float''.hex()</code> : renvoie une chaîne de caractères correspondant à l'écriture du nombre en hexadécimal ; * <code>''float''.fromhex(''c'')</code> : transforme une chaîne de caractères, correspondant à l'écriture d'un nombre en hexadécimal, en un nombre réel correspondant. Par exemple : <syntaxhighlight lang="python"> a = 20. print(a.hex()) # 0x1.4000000000000p+4 print(10..hex()) # 0x1.4000000000000p+3 </syntaxhighlight> Dans le deuxième exemple, nous appliquons la méthode <code>''float''.hex()</code> directement au nombre <code>10.</code> ; le point est obligatoire car sinon, c'est un entier, pour lequel la méthode n'est pas définie. On aurait pu aussi écrire <code>print(10.0.hex())</code>. Notez que la ''méthode'' <code>''float''.hex()</code> est différentes de la ''fonction'' <code>hex()</code> : la première concerne les réels, la seconde les entiers. ==== Complexes ==== Nous avons déjà mentionné la méthode <code>''complex''.conjugate()</code> qui donne le conjugué du nombre. Un nombre complexe dispose de deux attributs : * <code>''complex''.real</code> : sa partie réelle ; * <code> ''complex''.imag</code> : sa partie imaginaire. Par exemple : <syntaxhighlight lang = "python"> a = 5+2j print(a.conjugate(), ";", a.real, ";", a.imag) # (5-2j) ; 5.0 ; 2.0 </syntaxhighlight> === Chaînes de caractères === ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/inputoutput.html | titre = 7. Input and Output | site = Python Documentation | consulté le = 2019-04-06 }} : {{lien web | url = https://docs.python.org/3/library/string.html | titre = <code>string</code> — Common string operations | site = Python Documentation | consulté le = 2026-06-05 }} ==== Généralités ==== Il existe en fait trois manières de définir une chaîne de caractères : * avec des guillemets simples ou doubles comme vu précédemment : <code>"…"</code> ou bien <code>'…'</code> ; * avec trois guillemets doubles : <code>"""…"""</code> : cela permet d'avoir une chaîne de caractères s'étendant sur plusieurs lignes, les retours de ligne étant pris en compte ; c'est utilisé en particulier pour la description des fonctions (''{{lang|en|docstrings}}'', voir ci-après) ; * avec des guillemets précédés d'un « r », <code>r"…"</code> ou <code>r'…'</code> : cela permet d'interpréter les barres de fraction inverses « \ » comme un caractère « normal » et non comme un caractère d'échappement (voir ci-après) ; cela est utile lorsque l'on utilise les possibilités LaTeX dans le tracé de graphiques (voir plus loin) ; * avec des guillemets précédés d'un « f », <code>f"…"</code> ou <code>f'…'</code> : cela permet d'utiliser des variables formatées (voir ci-après). Une chaîne de caractères n'est pas modifiable. Si l'on veut remplacer un caractère, l'insérer ou le supprimer, il faut transformer la chaîne en liste, avec la commande <code>list()</code>, puis rassembler la liste en la joignant ''({{lang|en|join}})'' à une chaîne vide : <syntaxhighlight lang="python"> chaine = "blabla" chaineList = list(chaine) chaineList[2] = "c" chaine = "".join(chaineList) print(chaine) # blcbla </syntaxhighlight> Dans une chaîne simple <code>"…"</code> ou <code>'…'</code>, on peut introduire un retour à la ligne avec <code>\n</code>. Chaque caractère possède un code ''({{lang|en|code point}})'' définit par la norme Unicode ''({{lang|en|Unicode code point}})''. Pour afficher le caractère correspondant à un code, on utilise <code>chr()</code>. Pour afficher le code correspondant à un caractère, on utilise <code>ord()</code> <syntaxhighlight lang="python"> print(ord("a")) # 97 print(hex(ord("a"))) # 0x61 print(chr(97)) # a print(chr(0x61)) # a </syntaxhighlight> ==== Substitution de variables ==== Lorsque l'on veut utiliser des variables, on fait précéder les guillemets d'un « f » et l'on écrit les noms de variables entre accolades ; on parle de « chaîne f » ''(f-string)''. Par exemple : <syntaxhighlight lang="python"> monde = "world" chaine = f"Hello {monde}!" print(chaine) # Hello world! </syntaxhighlight> On peut indiquer la taille de la chaîne générée à partir de la variable sous la forme <code>{nomVariable:taille}</code>, la taille étant un entier. Par exemple : <syntaxhighlight lang="python"> chiffre1 = 1 nom1 = "un" chiffre2 = 2 nom2 = "deux" chaine = f"{nom1:5} : {chiffre1:5d}\n{nom2:5} : {chiffre2:5d}" print(chaine) # un : 1 # deux : 2 </syntaxhighlight> Vous remarquez que l'on ajoute un « d » pour les entiers décimaux, et que les nombres sont alignés à droite. Si le nombre est un nombre réal à virgule flottante ''({{lang|en|float}})'', on peut indiquer le nombre de décimales sous la forme <code>.''n''f</code> : <syntaxhighlight lang="python"> chaine = f"{np.pi:.5f}" print(chaine) # 3.15169 </syntaxhighlight> Avec la syntaxe <code>''m''.''n''f</code>, on indique également que la totalité du nombre doit occuper ''m'' caractères. Pour un nombre en notaiton scientifique (exponentielle), on utilise <code>.''n''e</code>. Pour convertir un nombre en caractère Unicode correspondant, on utilise la lettre c : <syntaxhighlight lang="python"> nompi = 0x03c0 # Caractère Unicode π : U+03C0 chaine = f"{nompi:c} = {np.pi:.5f}" print(chaine) # π = 3.14159 </syntaxhighlight> Le tiret de soulignement « <code>_</code> » (''underscore'', tiret du 8) permet de séparer les chiffres avant le séparateur décimal par groupe de trois chiffres séparés du tiret ; la virgule « <code>,</code> » les sépare d'une virgule. <syntaxhighlight lang="python"> print(f"{1e6:_}, {1e6:,}") # 1_000_000.0, 1,000,000.0 </syntaxhighlight> La classe ''str'' dispose également de la méthode <code>.format()</code>. On indique un n-uplet de chaînes (ou de nombres) à la méthode et l'on met des accolades dans la chaîne principale ; les accolades sont remplacées dans l'ordre des chaînes de la méthode. On peut changer l'ordre en indiquant quelle valeur utiliser dans quelle accolade. Par exemple : <syntaxhighlight lang="python"> chaine1 = "On compte {} puis {}".format(1, 2) chaine2 = "On compte {0} puis {1}. Mais à rebours, on compte {1} puis {0}.".format("un", "deux") print(chaine1, "\n", chaine2) # On compte 1 puis 2 # On compte un puis deux. Mais à rebours, on compte deux puis un. </syntaxhighlight> L'utilisation du caractère pourcent « % » permet d'utiliser la mise en forme <code>sprintf()</code> du langage C : <syntaxhighlight lang="python"> chaine = "π = %.5f" % np.pi print(chaine) # π = 3.14159 </syntaxhighlight> ; Exemple <nowiki>:</nowikI> barre de progression : Voici une fonction affichant une barre de progression, pour la ''i''-ème étape d'un processus ayant ''n'' étapes (pour la notion de fonction, voir la section ci-après ''[[#Fonction|Fonction]]''). : NB : nous avons utilisé les codes Unicode pour l'exemple, mais on peut évidemment copier le caractère, par exemple depuis une table Unicode ou une page Web<ref>Pour le point médian : ''{{W|Table des caractères Unicode/U0080}}'' ou ''{{W|Point médian}}''. Pour le pavé : ''{{W|Table des caractères Unicode/U2580}}''.</ref>, et le coller dans le code, comme nous l'avons fait dans le commentaire. <syntaxhighlight lang="Python"> def barre_progression(i, n, largeur=40): """ Affiche une barre de progression Entrées : — i : étape en cours, entier ; — n : nombre d'étapes à réaliser, entier ; — largeur : nombre de caractères total de la barre, entier. Sortie : affichage de la barre de progression. """ taux = i/n fait = int(largeur * taux) barre = f"{0x2588:c}" * fait + f"{0x00b7:c}" * (largeur - fait) # U+2588 : pavé "█" ; U+00B7 : point médian "·" print(f"Progression | {barre} | {100*taux:3.1f} %", end="\r") barre_progression(25, 100) # Progression | ██████████······························ | 25.0 % </syntaxhighlight> ==== Méthodes des chaînes ==== Le type ''str'' dispose d'un certain nombre de méthodes. Nous avons déjà vu les méthodes <code>''str''.join()</code> et <code>''str''.format()</code>, en voici quelques autres : * <code>''str''.capitalize()</code> : met le premier caractère en capitale (majuscule) et les autres en minuscule ; * <code>''str''.lower()</code> : met tout en minuscules ''({{lang|en|lowercase}})'' ; * <code>''str''.upper()</code> : met tout en capitales ''({{lang|en|lowercase}})'' ; * <code>''str''.center(''n'')</code> : met la chaîne au centre d'une chaîne de longueur ''n'', en complétant avec des espaces ; on peut compléter avec d'autres caractères avec <code>''str''.center(''n'', ''c'')</code>, par exemple <code>"a".center(7, ".")</code> donne <code>"....a...."</code> ; * <code>''str''.ljust(''n'', ''c'')</code> et <code>''str''.rjust(''n'', ''c'')</code> : comme <code>.center()</code> mais la chaîne est respectivement alignée au fer à gauche ''({{lang|en|left}})'' et à droite ''({{lang|en|right}})'' ; * <code>''str''.isdigit()</code> : booléen vrai si tous les caractères sont des nombres ; * <code>''str''.find(''sous-chaine'')</code>, <code>''str''.rfind(''sous-chaine'')</code> : indique respectivement le premier emplacement et le dernier emplacement de la sous-chaîne dans la chaîne, ou bien <code>-1</code> si la sous-chaîne est absente ; * <code>''str''.partition(''séparateur'')</code> : retourne un triplet avec la portion de chaîne avant le séparateur, le séparateur puis la portion de chaîne après le séparateur ; * <code>''str''.replace(''ancien'', ''nouveau'')</code> : remplace la chaîne ''ancien'' par la chaîne ''nouveau'' dans la chaîne ; * <code>''str''.split(''séparateur'')</code> : découpe la chaîne au niveau des séparateurs et renvoie une liste. ==== Autres fonctions ==== La fonction <code>chr()</code> transforme un code Unicode en caractère. Par exemple, <code>chr(97)</code> donne <code>"a"</code> et <code>chr(0x03c0)</code> donne <code>"π"</code>. Si on veut créer une liste de caractères qui se suivent, on peut par exemple utiliser : <syntaxhighlight lang="python"> [chr(x) for x in range(97, 102)] # ['a', 'b', 'c', 'd', 'e'] </syntaxhighlight> Si on veut créer une liste de nombres sous la forme de chaînes de caractères, on peut utiliser la commande <code>str()</code> vue ci-dessus. Par exemple : <syntaxhighlight lang="python"> [str(x) for x in range(1, 6)] # ['1', '2', '3', '4', '5'] </syntaxhighlight> Pour la syntaxe, voir ci-dessous la section [[#Définition en compréhension|''Définition en compréhension'']]. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = chr(0x2588) * fait + chr(0x00b7) * (largeur - fait) # U+2588 : bloc ; U+00B7 : point médian </syntaxhighlight> Rappel : le module <code>html</code> permet d'utiliser les entités HTML : <syntaxhighlight lang="python"> import html … print(html.entities.html5["alpha;"]+html.entities.html5["middot;"]) # α· </syntaxhighlight> L'entité HTML <code>&xxx;</code> s'obtient par <code>html.entities.html5["xxx;"]</code>, donc en enlevant la perluète ; mais cela ne fonctionne pas avec les codes Unicode. Pour cela, on peut utiliser la commande <code>html.unescape()</code>. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = html.unescape("&#x2588;") * fait + html.entities.html5["middot;"] * (largeur - fait) # U+2588 : bloc ; middot : point médian </syntaxhighlight> ou bien <syntaxhighlight lang="python"> barre = barre = html.unescape("&#x2588;" * fait + "&middot;" * (largeur - fait)) # U+2588 : bloc ; middot : point médian </syntaxhighlight> La commande <code>html.unescape()</code> interprète donc une chaîne complète, par exemple <syntaxhighlight lang="python"> print(html.unescape("L'esperluette est le caractère &laquo;&nbsp;&amp;&nbsp;&raquo;.")) # L'esperluette est le caractère « & ». </syntaxhighlight> == Manipulation de listes == Les listes sont une structure de données fondamentale en Python. ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/datastructures.html | langue = en | titre = 5. Data structures | site = Python documentation | consulté le = 2019-03-16 }} === Copie d'une liste === Contrairement à d'autres types, lorsque vos écrivez <code>b = a</code> avec des listes, vous ne créez pas une copie de la variable <code>a</code>, vous créez un ''alias'' : l'objet <code>b</code> est un autre nom de l'objet <code>a</code>. En particulier, si vous modifiez <code>b</code>, vous modifiez en fait <code>a</code>. Par exemple : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a b[2] = 5 print(a, b) # [1, 2, 5, 4] [1, 2, 5, 4] </syntaxhighlight> Si l'on veut créer une copie de <code>a</code>, il faut utiliser <code>a[:]</code> ou bien <code>a.copy()</code> : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a[:] c = a.copy() b[2] = 5 c[2] = 6 print(a, b, c) # [1, 2, 3, 4] [1, 2, 5, 4] [1, 2, 6, 4] </syntaxhighlight> === Méthodes de listes === Pour modifier une liste, vous disposez des méthodes suivantes : * <code>a.append(x)</code> : ajoute l'élément <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.extend(x)</code> : ajoute la liste <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.append(i, x)</code> : aoute l'élément <code>x</code> ''avant'' l'interstice ''i'' de la liste <code>a</code> ; * <code> x = a.pop(i)</code> : enlève l'élément ''i'' de la liste <code>a</code> et le met dans la variable <code>x</code> ; <code> x = a.pop()</code> enlève le dernier élément de la liste ; * <code>a.clear()</code> : vide la liste <code>a</code> ; * <code>a.sort()</code> : trie la liste par ordre croissant ; * <code>a.sort(reverse = True)</code> : trie par ordre décroissant ; * <code>a.reverse()</code> : inverse l'ordre de <code>a</code>. Pour supprimer l'élément à l'indice ''i'', au lieu d'utiliser <code>a.pop(i)</code>, on peut aussi utiliser <syntaxhighlight lang="python"> del(a[i]) </syntaxhighlight> Pour trier une liste, on peut aussi utiliser la fonction <code>sorted()</code>, ce qui permet par exemple de conserver la liste originale, non triée : <code>b = sorted(a)</code>. La fonction <code>sorted()</code> fonctionne avec tous les objets « itérables » comme par exemple une chaîne de caractères : <syntaxhighlight lang="python"> a = "ahjbfk" print(sorted(a)) # ['a', 'b', 'f', 'h', 'j', 'k'] </syntaxhighlight> Pour mettre en évidence la performance de la méthode <code>''list''.sort()</code> par rapport à la fonction générique <code>sorted()</code> : <syntaxhighlight lang="python"> import numpy as np import time a = np.random.rand(int(1e7)) t1 = time.perf_counter() b = sorted(a) # Fonction générique t2 = time.perf_counter() a.sort() # Méthode spécifique t3 = time.perf_counter() print("Sorted :", t2-t1, " s ; .sort :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # Sorted : 14.2... s ; .sort : 1.1... s ; rapport : 12.6... </syntaxhighlight> Par rapport à une valeur donnée : * <code>a.remove(x)</code> : retire la première occurrence de la valeur <code>x</code> de la liste <code>a</code> ; * <code>a.index(x)</code> : indique l'indice où se trouve la première occurrence de la valeur <code>x</code> ; * <code>a.count(x)</code> : indique le nombre de fois que l'on trouve la valeur <code>x</code> dans la liste <code>a</code>. === Définition en compréhension === La [[w:fr:Liste en compréhension|définition en compréhension]] ''({{lang|en|list comprehension}})'' est une méthode permettant de construire des listes en indiquant simplement des axiomes, des consignes de filtrage. Cette méthode est élégante car proche de la notation mathématique et compacte, mais c'est une méthode itérative donc lente par rapport à une méthode vectorisée fournie par le module NumPy. Par exemple, pour créer la liste des carrés des nombres entiers entre 0 et 9, il suffit d'écrire <syntaxhighlight lang="python"> carre = [x**2 for x in range(10)] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x^2 | x \in [0 ; 9] \}</math>. Si l'on veut la liste des nombres strictement inférieurs à 20 dont le carré est supérieur à 10, on peut écrire : <syntaxhighlight lang="python"> X = [x for x in range(20) if x**2 > 10] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x | x \in [0 ; 19], x^2 > 10 \}</math>. Pour mettre en évidence la performance du calcul vectorisé par rapport à la méthode itérative : <syntaxhighlight lang="python"> import time import numpy as np n = int(1e7) # taille de la liste t1 = time.perf_counter() carre = [x**2 for x in range(n)] # Définition en compréhension t2 = time.perf_counter() carre2 = np.arange(n)**2 # Calcul vectorisé t3 = time.perf_counter() print("En compréhension : ", t2-t1, "s ; vectorisé :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # En compréhension : 4.515... s ; vectorisé : 0.156... s ; rapport : 28.982... </syntaxhighlight> == Structure d'un programme == Un programme est simplement une suite d'instructions. Dans les environnements Unix BSD, un programme Python peut être considéré comme un script c'est-à-dire qu'il suffit de taper son nom dans l'invite de commande ''({{lang|en|shell}})'' sans avoir à invoquer <code>python</code>. Le programme doit alors commencer par un en-tête normalisé surnommé ''{{lang|en|[[wikt:shebang|shebang]]}}'' : <syntaxhighlight lang="python"> #!/usr/bin/env python3 </syntaxhighlight> Ce ''{{lang|en|shebang}}'' est inutile avec Jupyter. L'en-tête peut également contenir la description de l'encodage du fichier texte, typiquement : <syntaxhighlight lang="python"> # coding: utf-8 </syntaxhighlight> Le codage UTF-8 est le codage par défaut pour Python 3, il est donc inutile de l'indiquer. Les commentaires sont introduits par le croisillon <code>#</code>. On peut grouper une suite d'instructions dans un bloc. Un bloc d'instructions commence par deux-points « <code>:</code> » et est identé, c'est-à-dire qu'il a une marge constituée de quatre espaces — on peut aussi utiliser une tabulation mais il ne faut pas mélanger les deux méthodes ; les tabulations sont déconseillées, il vaut mieux utiliser quatre espaces<ref>{{lien web | url = https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces | titre = Tabs or Spaces? | site = Python documentation | consulté le = 2019-03-14 }}</ref>. Pour terminer le bloc, il suffit simplement de revenir en début de ligne ; contrairement à d'autres langages, il n'y a pas de commende de fin ''({{lang|en|end}})'', c'est l'indentation qui définit le bloc. : # début du bloc ''instruction 1'' ''instruction 2'' … ''dernière instruction du bloc'' ''instruction hors bloc'' Par exemple, une exécution conditionnelle <code>if</code> ou une boucle <code>for</code> exécute un bloc d'instruction. Si l'on a besoin d'un bloc d'instruction qui « ne fait rien », on utilise l'instruction <code>pass</code>. == Structures de contrôle == '''Boucle itérative''' La boucle itérative s'écrit : <syntaxhighlight lang="python"> for <variable> in <itérable>: <bloc d’instructions> </syntaxhighlight> Si l'on veut que la variable prenne ''n'' valeurs de 0 à ''n'' – 1, on utilise l'instruction <code>range()</code> : <syntaxhighlight lang="python"> for i in range(5): print(i) print("Fin de la boucle") </syntaxhighlight> <code>[▶]</code> 0 1 2 3 4 Fin de la boucle En fait, la commande <code>range()</code> extrait des valeurs de l'ensemble des nombres entiers ; on peut ainsi utiliser le découpage en tranches, par exemple <code>range(2, 5)</code>pour avoir la « liste » <code>[2, 3, 4]</code>. Notez que <code>range()</code> ne crée pas à proprement parler une liste, cela crée un objet de type ''« {{lang|en|range}} »'' (plage, intervalle) ; pour avoir une liste, il faut écrire <code>list(range(n))</code>. Dans une boucle, la commande <code>continue()</code> saute la fin du bloc d'instruction et passe à la valeur suivante de la boucle. La commande <code>break()</code> interrompt la boucle et passe à la suite. '''Exécution conditionnelle''' L'exécution conditionnelle s'écrit : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> </syntaxhighlight> On peut utiliser les commandes <code>elif</code> ''(else if'') et <code>else</code> : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> elif <booléen>: <bloc d’instructions> else: <bloc d’instructions> </syntaxhighlight> Notez que le test d'une condition est gourmand en ressources. S'il s'agit de savoir si l'on effectue une opération mathématique simple ou pas, on peut remplacer le test par une multiplication par un booléen (<code>True</code> vaut 1, <code>False</code> vaut 0). Par exemple, plutôt que d'écrire <syntaxhighlight lang="python"> if a > 0: b = b - c </syntaxhighlight> mieux vaut écrire : <syntaxhighlight lang="python"> b = b - (a > 0)*c </syntaxhighlight> '''Boucle antéconditionnée''' La boucle antéconditionnée s'écrit : <syntaxhighlight lang="python"> while <booléen>: <bloc d’instructions> </syntaxhighlight> Cette boucle peut contenir des instructions <code>continue()</code> et <code>break()</code>. == Fonction == La déclaration d'une fonction utilise la commande <code>def</code>. La fonction est un bloc d'instructions. Si elle doit renvoyer des valeurs, on utilise la commande <code>return</code>. Par exemple <syntaxhighlight lang="python"> def nombres(n): """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo a = nombres(3) print(a) </syntaxhighlight> La fonction commence par une chaîne de caractères qui la décrit. Cette chaîne peut être récupérée automatiquement par certains logiciels pour faire une documentation automatique. Si la description prend plusieurs lignes, elle commence et finit par trois double-guillemets <code>"""…"""</code> ; en fait, par convention, même si cela n'est pas obligatoire, les descriptions sont toutes encadrées de trois double-guillemets. Cette description est appelée ''{{lang|en|docstring (documentation string)}}''. Pour récupérer les ''{{lang|en|docstrings}}'' : <syntaxhighlight lang="python"> def foo(): """Cette fonction ne fait rien""" pass print(foo.__doc__) # Cette fonction ne fait rien </syntaxhighlight> L'instruction <code>input()</code> permet à l'utilisateur de saisir une valeur. La valeur est retournée sous la forme d'une chaîne de caractères qui est ensuite convertie en nombre réel avec l'instruction <code>float()</code>. On peut définir une valeur par défaut en l'indiquant dans l'en-tête de la définition de la fonction, de la manière suivante : <syntaxhighlight lang="python"> def nombres(n=1): # valeur par défaut : 1 """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo </syntaxhighlight> Si le paramètre à initialiser est de type modifiable ''({{lang|en|mutable}})'', comme par exemple une liste, il faut procéder comme suit : <syntaxhighlight lang="python"> def fooFonction(fooListe=None): # valeur par défaut : n'existe pas """Description""" if fooListe = None: fooListe = [] # initialisation <suite des instructions> </syntaxhighlight> Par défaut, les variables sont locales. On peut rendre une variable globale avec l'instruction <code>global</code> ''à l'intérieur de la fonction'', avant l'utilisation de la variable. Par exemple : <syntaxhighlight lang="python"> a = 1 b = 1 def toto(): """Test de variable globale. Entrée : aucune. Sortie : aucune.""" global a a = 2 b = 2 toto() print("a =", a, "; b =", b) # a = 2 ; b = 1 </syntaxhighlight> Pour être plus précis : si une variable n'est pas assignée dans une fonction, alors Python va chercher une variable du même nom à l'extérieur de la fonction. Mais à partir du moment où la variable est assignée dans la fonction, elle devient locale ''sauf'' si l'on a utilisé l'instruction <code>global</code>. Si l'on s'attend à un nombre indéfini d'arguments, on utilise la notion d'empaquetage/dépaquetage ''({{lang|en|packing/unpacking}})''<ref>{{lien web | url = https://deusyss.developpez.com/tutoriels/Python/args_kwargs/ | titre = Introduction à *args et **kwargs | consulté le = 2019-03-09 | site = Developpez.com }}.</ref>. L'empaquetage consiste à mettre les arguments dans un n-uplet, le dépaquetage consiste à développer un n-uplet en plusieurs variables. Cela se fait en mettant un astérisque ''({{lang|en|splat}})'' « <code>*</code> » devant le nom de la variable. Par convention, on utilise le nom de variable <code>*args</code> mais cela n'est pas obligatoire. <syntaxhighlight lang="python"> def concatenation(*args): """Concatène des chaînes de caractères Entrée : *args, n-uplet de chaînes de caractères. Sortie : resultat, chaîne de caractères.""" resultat = "" for i in args: resultat = resultat + i return resultat concatenation("a", "foo", "toto") # 'afoototo' </syntaxhighlight> À l'inverse, si une fonction doit recevoir plusieurs paramètres, on peut à la place lui transmettre une liste à dépaqueter : <syntaxhighlight lang="python"> def addition(a, b): """Ajoute deux nombres Entrées : — a : réel ; — b : réel. Sortie : a+b, réel""" return a+b arg = (1, 2) addition(*arg) # 3 </syntaxhighlight> On peut aussi empaqueter/dépaqueter un dictionnaire, on utilise pour cela deux astérisques « <code>**</code> ». Par convention, on utilise le nom <code>**kwargs</code> sans que cela soit obligatoire. L'instruction <code>lambda</code> permet de créer de petites fonctions ne contenant pas de boucle ni de branchement conditionnel. Cependant, si la déclaration est courte et compacte, le code n'est pas toujours facilement lisible ; l'utilisation de cette instruction n'est pas recommandée. Par exemple l'expression <syntaxhighlight lang="python"> f = lambda x: 2*x </syntaxhighlight> est la même chose que <syntaxhighlight lang="python"> def f(x): """Calcule le double. Entrée : x, réel. Sortie : 2*x, réel.""" return 2*x </syntaxhighlight> {{note|L'instruction <code>eval()</code> exécute une chaîne de caractères, c'est-à-dire traite une chaîne de caractères comme si c'étaient des instructions données à Python. Cette instruction est à éviter pour deux raisons : # Un utilisateur malveillant pourrait entrer du code malveillant dans la chaîne de caractères. # L'exécution est lente puisque Python doit compiler la chaîne à la volée. Cette instruction peut en général être remplacée par une autre instruction. }} == Gestion des erreurs == Dans un bloc d'instructions, on peut utiliser la structure <code>try:… except:</code>. Le bloc après <code>try</code> est exécuté ; si une erreur se déclare dans ce bloc, alors le bloc <code>except</code> s'exécute. Par exemple <syntaxhighlight lang="python"> try: 1/0 # Génère une erreur except: print("Division par zéro") # Cette instruction est donc exécutée </syntaxhighlight> On peut compléter avec <code>else:</code> et <code>finally:</code> : <syntaxhighlight lang="python"> try: <code à exécuter> except: <s’exécute en cas d’erreur> else: <s’exécute s’il n’y a pas d’erreur> finally: <s’exécute dans tous les cas> </syntaxhighlight> On peut séparer les différents types d'erreur : <syntaxhighlight lang="python"> try: <code à exécuter> except ValueError: print("Valeur erronée") except TypeError: print("Type erroné") </syntaxhighlight> Les types d'erreur les plus courants sont : * <code>NameError</code> : le nom de variable n'existe pas ; * <code>TypeError</code> : la valeur n'est pas du bon type ; * <code>ValueError</code> : la valeur n'est pas compatible avec ce qui est attendu ; * <code>RuntimeError</code> : type d'erreur général. On peut aussi créer ses propres erreurs : si une situation erronée survient, on peut « lever » une exception avec <code>raise</code>. Par exemple <syntaxhighlight lang="python"> if a < 0: raise ValueError("La valeur doit être positive") </syntaxhighlight> ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/errors.html | titre = Errors and exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} * {{lien web | url = https://docs.python.org/3/library/exceptions.html | titre = Built-in Exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} == Exercices == === Calcul du PGCD et du PPCM par l'algorithme d'Euclide === {{loupe|w:Algorithme d'Euclide}} Écrire un programme Python qui demande deux nombres entiers et affiche leurs PGCD et PPCM. Le programme utilisera l'algorithme d'Euclide. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """Programme : euclide.py Auteur : User:cdang date : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : calcule le PGCD et le PPCM de deux nombres entiers. Entrée ------ au clavier, saisie de deux nombres entiers. Sorties ------- à l'écran, affichage du PGCD et du PPCM. """ # *************** # *************** # ** Fonctions ** # *************** # *************** def euclide(): """Calcule le PGCD et le PPCM avec l'algorithme d'Elclide Entrée ------ Aucune, la saisie des paramètres fait partie de la fonction Sortie ------ affichage du PGCD et du PPCM """ print("***** Algorithme d'Euclide *****\n") a0 = int(input("Premier nombre entier : a = ")) b0 = int(input("Second nombre entier : b = ")) a = a0 b = b0 r = a%b # initialisation while (r != 0) : # algorithme d'Euclide a = b b = r r = a%b # affichage des résultats print("PGCD(", a0, ", ", b0, ") = ", b) print("PPCM(", a0, ", ", b0, ") = ", a0*b0//b) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* euclide() </syntaxhighlight> On peut simplifier la boucle centrale : <syntaxhighlight lang="python"> while b: # s'exécute tant que b n'est pas 0 a, b = b, a % b # affectation de liste à liste return a </syntaxhighlight> {{boîte déroulante fin}} Notez que le module NumPy propose l'instruction <code>gcd()</code> : <syntaxhighlight lang="python"> import numpy … print(numpy.gcd(a, b)) </syntaxhighlight> === Tours de Hanoï === {{loupe|w:Tours de Hanoï}} Écrire un programme Python qui demande le nombre ''n'' de plateaux et affiche les manipulations nécessaires pour déplacer la pile d'un emplacement à un autre. Le programme utilisera l'algorithme récursif. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """nom : hanoi.py auteur : User:cdang date de création : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : résout le problème des tours de Hanoï Entrées ------- trois chaînes de caractères (nom des piliers) Sorties ------- une chaîne de caractères (liste des opérations) """ # *************** # *************** # ** Fonctions ** # *************** # *************** def hanoi(a, b, c, n): """Résout le problème des tours de Hanoï de manière récursive But : déplace la pile de n disques du piler a au pilier b Entrées ------- a, b c : chaînes de 1 caractère, référence des emplacements ; n : entier, nombre de disques sur l'emplacement a Sorties ------- operations : chaînes de caractères décrivant les opérations """" if n>1: operations = hanoi(a, c, b, n-1) operations = operations+a+"→"+b+" ; " operations = operations+hanoi(c, b, a, n-1) else: operations = a+"→"+b+" ; " return operations # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* resultat = hanoi("1", "2", "3", 3) print(resultat) </syntaxhighlight> {{boîte déroulante fin}} === Lancer de rayons === [[Fichier:Lentille hemispherique perspective.svg|vignette|Lentille hémisphérique.]] Considérons une lentille hémisphérique de rayon R faite d’un verre d’indice de réfraction ''n''. Nous plaçons une source ponctuelle à une distance ''d'' du dioptre plan, sur l’axe optique. Tracer des rayons partant de la source et traversant la lentille. {{clear}} {{Boîte déroulante/début |titre=Analyse d’optique géométrique}} [[Fichier:Lentille hemispherique analyse geometrique.svg|vignette|Analyse géométrique du problème.]] Il s’agit d’un problème ayant une symétrie de révolution par rapport à l’axe optique. Nous pouvons nous réduire à un problème plan en nous plaçant dans un plan contenant l’axe optique ; l’axe optique est encore un axe de symétrie orthogonale, nous pouvons donc nous contenter d'étudier un demi-plan. Pour simplifier, nous plaçons le centre du dioptre sphérique à l’origine O du repère. L’axe optique est l’axe ''x'' et l'axe perpendiculaire, vertical sur la figure, c’est l’axe ''y''. Les coordonnées de la source sont donc (-''d'' ; 0). Le rayon issu de la source et faisant un angle θ avec l’axe ''x'' frappe le dioptre plan à l’altitude ''h''. Nous avons : : ''h'' = ''d'' ⋅ tan θ. L’angle d’incidence vaut θ. D’après la loi de Snell-Descartes, l'angle de réfraction θ<sub>2</sub> vaut : : θ<sub>2</sub> = arcsin((sin θ) / ''n''). Le rayon réfracté passe par le points de coordonnées (0, ''h''). L’équation de la droite est donc : : ''y'' = a ⋅ ''x'' + ''h'' avec : ''a'' = tan θ<sub>2</sub>. L’équation du cercle de centre O et de rayon R est : : ''x''<sup>2</sup> + ''y''<sup>2</sup> = R<sup>2</sup>. Les coordonnées (''x''<sub>M</sub>, ''y''<sub>M</sub>) de l’intersection M du rayon avec le dioptre sphérique vérifient les deux équations. Par substitution, nous obtenons une équation du second degré en ''x'' que nous savons résoudre : : ''x''<sub>M</sub><sup>2</sup> + (''a'' ⋅ ''x''<sub>M</sub> + ''h'')<sup>2</sup> = R<sup>2</sup> : ⇔ (1 + ''a''<sup>2</sup>) ⋅ ''x''<sub>M</sub><sup>2</sup> + 2 ⋅ ''a'' ⋅ ''h'' ⋅ ''x''<sub>M</sub> + ''h''<sup>2</sup> – R<sup>2</sup> = 0. D’après les propriétés du cercle, le rayon est perpendiculaire à la tangente. Le rayon [OM] est donc normal au dioptre en M. Nous pouvons déterminer l’angle d’incidence θ<sub>i</sub> par le produit scalaire : : <math>\begin{pmatrix} 1 \\ a \end{pmatrix} \cdot \begin{pmatrix} x_\mathrm{M} \\ y_\mathrm{M} \end{pmatrix} = \sqrt{1^2 + a^2} \cdot \mathrm{R} \cdot \cos(\theta_\mathrm{i})</math> ce qui nous permet de calculer cet angle : : <math>\theta_\mathrm{i} = \operatorname{arcos} \left ( \frac{x_\mathrm{M} + a \cdot y_\mathrm{M}}{\mathrm{R} \cdot \sqrt{1^2 + a^2} } \right )</math> Comme nous passons vers un milieu d’indice plus faible, il y a un risque de réflexion totale. L’angle limite est : : θ<sub>max</sub> = arcsin(1/''n''). Si l’on a θ<sub>i</sub> &gt; θ<sub>max</sub>, le rayon repart vers l’intérieur. Nous ne traçons pas le rayon car cela nous emmènerait trop loin dans l’analyse. En revanche, si θ<sub>i</sub> ≤ θ<sub>max</sub>, alors nous pouvons appliquer la loi de Snell-Descartes pour avoir l’angle de réfraction θ<sub>e</sub> : : θ<sub>e</sub> = arcsin(''n'' ⋅ sin θ<sub>i</sub>). Pour tracer le rayon sortant, il nous faut l’angle θ<sub>3</sub> par rapport à l’horizontale. L’angle du rayon [OM] par rapport à l’horizontal vaut arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>), nous avons donc : θ<sub>3</sub> = arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>) + θ<sub>e</sub>. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Analyse algorithmique}} '''Structure des données''' Le problème est décrit par trois paramètres : # Le rayon <code>R1</code> de la lentille, en milliètres (réel en virgule flottante). # L’indice du verre, <code>n</code> sans dimension (réel en virgule flottante). L’indice de l’air vaut 1. # La distance de la source au dioptre d’entrée plan, <code>d</code> en millimètres (réel en virgule flottante). Un rayon est caractérisé par quatre paramètres : # L’angle d’émission <code>theta1</code> en radians (réel en virgule flottante). # L’angle de réfraction dans la lentille <code>theta2</code> en radians (réel en virgule flottante). # Les cordonnées <code>M</code> en millimètre (vecteur de dimension 2 <code>([x, y])</code> de réels en virgule flottante) du point d’intersection du rayon avec le dioptre sphérique. # L’angle de réfraction dans l’air après la lentille <code>theta3</code> en radians (réel en virgule flottante). Pour le calcul et le tracé, nous avons besoin des paramètres intermédiaires suivants : * l’altitude ''y'' = <code>h</code> en millimètres (réel en virgule flottante) à laquelle le rayon frappe le dioptre plan d’entrée ; * l’angle d’incidence du rayon avec le dioptre sphérique <code>thetaint</code> en radians (réel en virgule flottante). Les angles sont stockés en radians car c’est l’unité naturelle pour le calcul mais nous affichons les valeurs en degrés. Comme le calcul de conversion est récurrent, nous conservons les facteurs <code>degversrad</code> (conversion des degrés vers les radians, facteur valant π/180, réel en virgule flottante) et <code>radversdeg</code> (conversion des radians vers les degrés, facteur valant 180/π, réel en virgule flottante). '''Fonctions''' Nous avons besoin d’une fonction qui calcule les trois paramètres du rayon <code>(theta2, M, theta3)</code> à partir de l’angle d’émission <code>theta1</code>. Nous appelons cette fonction <code>lanceRayon()</code>. Cette fonction fait appelle à une fonction qui calcule l’angle du rayon réfracté à partir de l’angle du rayon incident <code>theta1</code>, les deux angles étant par rapport à la normale au dioptre au point considéré. Nous appelons cette fonction <code>refrac()</code>. La recherche de l’intersection <code>M</code> du rayon avec le dioptre sphérique nécessite de résoudre une équation du second degré. Nous utilisons pour cela la recherche des racines du polynôme en <code>x</code> avec la fonction <code lang="python">numpy.polynomial.polynomial.polyroots()</code>. D’après la configuration du problème géométrique, si l’on s’assure que le rayon frappe bien la lentille (0 ≤ <code>h</code> ≤ <code>R1</code>) alors nous sommes sûrs que le problème a deux solutions réelles (une positive et une négative) ou, dans le cas dégénéré où <code>h == R1</code>, une valeur unique <code>x == 0</code>. Comme nous recherchons la valeur positive, nous sélectionons la plus grande des deux racines. Pour la gestion de la réflexion interne : dans la fonction <code>refrac()</code>, nous vérifions les conditions de réflexion totale et si elles sont remplies, alors nous générons une erreur (commandes <code lang="python">try… except</code> et <code lang="python">raise ValueError</code>). Cette erreur est propagée à la fonction <code>lanceRayon()</code> : <code>lanceRayon()</code> appelle la fonction <code>refrac()</code> et si cette fonction renvoie une erreur, alors <code>lanceRayon()</code> renvoie également une erreur. Pour trouver l’angle d’émission <code>thetaLimite</code> provoquant la réflexion totale (en radians, réel en virgule flottante), nous effectuons une recherche par dichotomie : * nous partons de l’angle maximum possible, lorsque le rayon frappe le sommet de la lentille, et nous appelons la fonction <code>lanceRayon()</code> ; si cela ne génère pas d’erreur, alors nous pouvons aller jusqu’à cette valeur, la recherche est terminée ; si cela génère une erreur, alors nous divisons la valeur par deux ; * à une étape de la recherche donnée, si <code>lanceRayon()</code> ne génère pas d’erreur avec l’angle testé, alors nous savons que l’angle limite est supérieur à cette valeur ; cette valeur minore donc la valeur recherchée ; si au contraire <code>lanceRayon()</code> génère une erreur, alors c’est que l’angle est trop important, cette valeur majore donc la valeur recherchée ; nous pouvons ainsi resserer l’intervalle de recherche ; * nous nous arrêtons lorsque les valeurs haute et basse sont suffisamment proche. Concrètement : # Nous définissons une variable <code>angleHaut</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus bas connu provoquant la réflexion totale. # Nous définissons une variable <code>angleBas</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus haut connu ne provoquant pas de réflexion totale. Sa valeur initiale est 0. L’angle limite recherché est donc entre <code>angleBas</code> et <code>angleHaut</code>. # Nous définissons l’angle <code>angleTest</code> comme étant la moyenne entre <code>angleBas</code> et <code>angleHaut</code>. Si <code>lanceRayon(angleTest)</code> génère une erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleHaut</code> (puisque c’est une valeur provoquant la réflexion totale et qu’elle est plus basse que la valeur actuelle d’<code>angleHaut</code>). À l’inverse, si <code>lanceRayon(angleTest)</code> ne génère pas d’erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleBas</code> (puisque c’est une valeur ne provoquant pas la réflexion totale et qu’elle est plus haute que la valeur actuelle d’<code>angleBas</code>). # Nous arrêtons la procédure lorsque l’écart entre <code>angleBas</code> et <code>angleHaut</code> est inférieur à {{unité|10|échelle=<sup>–3</sup>|rad}} (valeur arbitraire). La valeur retenue est la valeur finale d’<code>angleBas</code> (puisque l’on veut être sûr qu’il n’y ait pas de réflexion totale). La valeur affichée est la valeur en degrés arrondie au dixième. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Solution}} Nous demandons à l’utilisateur ou à l’utilisatrice les valeurs des paramètres du problème : rayon de la lentille, distance de la source, indice de réfraction du verre. Nous vérifions que les valeurs entrées sont bien des nombres ; si c’est une chaîne vide, alors nous utilisons une valeur par défaut. Nous créons une fonction <code>refrac()</code> qui permet de calculer l’angle réfracté à partir de l’angle d’incidence et des indices de réfraction. S’il y a rélexion totale, alors nous générons une erreur. La fonction <code>lanceRayon()</code> calcule les différents points de passage du rayon. Elle appelle pour cela la fonction <code>refrac()</code>. Si un appel de la commande <code>refrac()</code> génère une erreur, alors nous générons également une erreur. Nous déterminons l’angle d’émision du rayon <code>thetaLimite</code> qui provoque une réflecxion totale. Pour cela, nous créons une fonction <code>rechercheLimite()</code> qui cherche par dichotomie. Nous traçons un rayon tous les 5° jusqu’à la valeur limite. <syntaxhighlight lang="python"> #!/usr/bin/env python3 # coding: utf-8 """nom : lancerRayons.py auteur : User:cdang date de création : 2022-05-06 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : NumPy, matplotlib ---------------------------------------------------------------------------- Objectif : trace des trajets optique avec une lentille hémisphérique Entrées ------- Le rayon de la lentille, la distance de la source, l’indice de réfraction du verre, trois chaînes de caractères saisies par l’utilisateur·rice et qui sont converties en réels. Sorties ------- La valeur limite de l’angle (réel) et le tracé de plusieurs rayons. """ # ****************************************************** # ****************************************************** # ** Lancer de rayons pour une lentille hémisphérique ** # ****************************************************** # ****************************************************** import numpy as np import matplotlib.pyplot as plt import numpy.polynomial.polynomial as nppol # ************** # * Constantes * # ************** # Pour la conversion degrés ↔ radians radversdeg = 180/np.pi degversrad = 1/radversdeg # ************* # * Fonctions * # ************* def boucleEntreeNombre(messageSaisie, valeurDefaut): """Permet de s’assurer que l’utilisateur·rice a bien entré un nombre. Entrée : — message à afficher (chaîne de caractères) ; — valeur par défaut (réel à virgule flottante). Sortie : nombre (réel à virgule flottante).""" messageErreur = "Veuillez entrer une valeur numérique (ou vide pour accepter la valeur par défaut).\n" execute = True while execute: strNombre = input(messageSaisie+f" (valeur par défaut {valeurDefaut}) : ") if strNombre == "": nombre = valeurDefaut execute = False else: try: nombre = float(strNombre) except: print(messageErreur) else: execute = False return nombre def initialisation(): """L’utilisateur·rice entre les variables du problème. Entrées : aucune. Sorties : — R1 (mm) : rayon de la lentille ; — d (mm) : distance de la source au dioptre plan ; — n (sans dimension) : indice de réfraction du verre.""" R1 = boucleEntreeNombre("Rayon de la lentille en mm", 20.0) d = boucleEntreeNombre("Distance de la source au dioptre plan en mm", 20.0) n = boucleEntreeNombre("Indice de réfraction (sans dimension)", 1.5) return (R1, d, n) def refrac(n1, n2, theta1): """Calcule l’angle de réfraction theta2 (radians) en fonction — de l’angle d’incidence theta1 (radians); — de l’indice de réfraction n1 du premier milieu ; — de l’indice de réfraction n2 du second milieu.""" reflexionTotale=False rapport=n2/n1 rapportinv=np.reciprocal(rapport) if n1 > n2: thetal = np.arcsin(rapport) # angle limite pour la réflexion totale if theta1 >= thetal: reflexionTotale=True if reflexionTotale: print("Réflexion totale") raise ValueError else: return np.arcsin(rapportinv*np.sin(theta1)) def lanceRayon(n1, n2, d, R, theta1): """Détermine le rayon issu de la source située à une distance d (mm) du bareau et avec une élévation de theta1 (radians), en fonction des indices de réfraction n1 et n2. Les éléments retournés sont : — la hauteur h (mm) à laquelle le rayon frappe le barreau ; — l’angle de réfraction theta2 (radians)) dans le barreau ; — l’angle de réfraction theta3 (radians) à la sortie du barreau — le point M(x, y) (mm) auquel le rayon sort du barreau.""" h = d*np.tan(theta1) if h >= R: print("Le rayon est au-dessus du barreau") raise ValueError else: theta2 = refrac(n1, n2, theta1) a = np.tan(theta2) x = max(nppol.polyroots([h*h - R*R, 2*a*h, 1+a*a])) # recherche de l’intersection du rayon avec le cercle y = a*x + h M = np.array([x, y]) thetaint = np.arccos((x + a*y)/(R*np.sqrt(1 + a*a))) theta3 = np.arctan(y/x) - refrac(n2, n1, thetaint) return (h, theta2, theta3, M) def rechercheLimite(n1, n2, d, R): """Recherche l’angle limite pour la réflexion totale. Entrée : — indice de réfraction des milieux 1 et 2, n1 et n2 ; — distance au barreau, d(mm). Sortie : angle limite theta (radians)""" angleHaut = np.arctan(R/d) angleBas = 0 angleTest = angleHaut try: lanceRayon(n1, n2, d, angleTest, R) except: condition = True # il y a réflexion total en haut de la lentille else: condition = False # il n’y a jamais réflexion totale dans la lentille while condition: #dichotomie angleTest = np.mean([angleHaut, angleBas]) # on ajuste la valeur de test try: lanceRayon(n1, n2, d, R, angleTest) except: angleHaut = angleTest # réflexion totale : on abaisse la valeur maximale else: angleBas = angleTest # pas de réflexion totale : on monte la valeur minimale condition = ((angleHaut - angleBas) >= 0.001) # on a cerné la limite à 0,001 rad près if not condition: angleTest = angleBas return angleTest # *********************** # * Programme principal * # *********************** (R1, d, n) = initialisation() xmax = round(R1 + d) thetaLimite = rechercheLimite(1, n, d, R1) thetaLimiteDeg = thetaLimite*radversdeg print(f"Angle limite pour la réflexion totale : {thetaLimiteDeg:.1f}°.\n") anglesDeg = np.arange(0, thetaLimiteDeg, 5)[1:] # trace un rayon tous les 5° anglesRad = anglesDeg*degversrad nb = len(anglesDeg) h = np.zeros(nb) # initialisation des vecteurs de valeurs theta2 = np.zeros(nb) theta3 = np.zeros(nb) M = np.zeros((nb, 2)) for i in range(nb): (h[i], theta2[i], theta3[i], M[i, :]) = lanceRayon(1, n, d, R1, anglesRad[i]) (h_lim, theta2_lim, theta3_lim, M_lim) = lanceRayon(1, n, d, R1, thetaLimite) # tracé anglesCercle = 0.5*np.pi*(np.linspace(1, 0, 20)) x_cercle = R1*np.cos(anglesCercle) # coordonnées des pints du cercle y_cercle = R1*np.sin(anglesCercle) fig = plt.plot([-d,xmax], [0, 0], "k-.", linewidth="0.5") # tracé de l’axe optique for i in range(nb): plt.plot([-d, 0, M[i, 0], xmax], [0, h[i], M[i, 1], M[i, 1] + (xmax - M[i, 0])*np.tan(theta3[i])], label=f"{anglesDeg[i]:.0f}°") plt.plot([-d, 0, M_lim[0], xmax], [0, h_lim, M_lim[1], M_lim[1] + (xmax - M_lim[0])*np.tan(theta3_lim)], label=f"{0.1*int(np.trunc(10*thetaLimite*radversdeg)):.1f}°") plt.plot(x_cercle, y_cercle, "k", linewidth="0.5") # tracé du cercle plt.plot([0,0], [0, R1], "k", linewidth="0.5") # tracé du premier dioptre #plt.axis("square") plt.gca().set_aspect("equal", adjustable="box") plt.xlabel("x (mm)") plt.ylabel("y (mm)") plt.title("Lentille hémisphérique, lancer de rayons") plt.legend() plt.savefig("lentille_hemispherique_lancer_rayon.svg", format="svg") plt.show() </syntaxhighlight> {{Boîte déroulante/fin}} == Mesurer le temps == Le module <code>time</code> fournit les fonctions suivantes : * <code>time.gmtime()</code> : renvoie la date et l'heure du méridien de Greenwich (''{{lang|en|Greenwich mean time}}'', GMT), sous la forme d'un dictionnaire (année, mois, jour du mois, heure, minute, seconde, jour de la semaine, jour de l'année, heure d'été/hiver), ** jour de la semaine est un entier entre 0 (lundi) et 6 (dimanche), ** jour du mois est un entier entre 1 et 366 ; * <code>time.localtime()</code> : comme le précédent, mais l'heure est l'heure locale ; * <code>time.time()</code> : donne le nombre de seconde qui se sont écoulées depuis le 1er janvier 1970 ; * <code>time.gmtime(n)</code> et <code>time.localtime(n)</code> transforment un nombre de secondes (écoulées depuis le 1er janvier 1970) en une date au format (année, mois, jour, etc.), n-uplet de neuf valeurs ; <code>time.mktime()</code> fait le contraire, il transforme un n-uplet de neuf valeurs (années, mois, jour, etc.) en un nombre de secondes (écoulées depuis le 1er janvier 1970) ; * <code>time.sleep(n)</code> : provoque une pause dans le déroulement du programme de ''n'' secondes ; * <code>time.perf_counter()</code> : indique une date en seconde ; s'utilise pour mesurer la durée d'exécution d'une partie du code, en faisant la différence entre deux relevés. Concernant la date et l'heure sous la forme d'un n-uplet, on peut extraire l'heure de la manière suivante : <syntaxhighlight lang="python"> import time a = time.localtime() print("Il est ", a[3], "h", a[4]) # ou bien print("Il est ", a.tm_hour, "h", a.tm_min) </syntaxhighlight> Pour mesurer la performance d'une portion de code : <syntaxhighlight lang="python"> import time t1 = time.perf_counter() <suite d’instructions> t2 = time.perf_counter() print("Durée d'exécution :", t2-t1 </syntaxhighlight> == Programmation orientée objet == Nous n'allons pas ici faire un cours de programmation orientée objet (POO), nous allons aborder le sujet de manière pragmatique. De manière schématique, un « objet » est une « super-variable ». Cette super-variable peut contenir plusieurs variables, appelées « attributs » ; elle contient en fait un dictionnaire (paires « nom d'attribut : valeur d'attribut »). Elle peut aussi contenir des fonctions spécifiques appelées « méthodes ». De même qu'une variable a un type, un objet fait partie d'une « classe ». La classe est le modèle de l'objet ; en franglais informatique, on dit que l'objet est une instance de la classe. La POO est donc un formalisme : lorsque l'on définit des variables et des fonctions concernant un même type d'objet (au sens commun du terme), on les empaquette dans une classe. Il faut donc d'abord définir la classe, puis attribuer cette classe à un objet (« instancier » la classe). Considérons par exemple que nous voulons travailler sur des [[w:Engrenage|engrenages]] ; pour simplifier, nous nous contentons d'engrenages à dentures droites. Une roue dentée, un pignon, est essentiellement définie par son nombre de dents Z et par son module ''m'' qui correspond à la largeur de dents<ref>ainsi que par son épaisseur ''e'' et le matériau dont elle est faite mais nous allons négliger ces paramètres pour la simplicité de l'étude.</ref>. Nous allons définir trois méthodes : la méthode <code>.diametrePrimitif()</code> qui calcule le diamètre primitif de la roue dentée, <code>.pas()</code> qui calcule la largeur des dents au niveau du cercle primitif et <code>.rapport()</code> qui calcule le rapport de transmission de deux roues engrenées Z<sub>1</sub>/Z<sub>2</sub>. La méthode <code>.rapport()</code> vérifie par ailleurs que les roues ont le même module, condition indispensable pour former un engrenage. Nous définissons la classe ainsi : <syntaxhighlight lang="python"> class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): # instructions lancées lors de la déclaration """Valeurs des attributs""" self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z </syntaxhighlight> Nous remarquons que lorsque nous déclarons les méthodes, le paramètre <code>self</code> correspond à l'objet lui-même. Ainsi, dans la méthode <code>.rapport()</code>, la variable <code>self.Z</code> est le nombre de dents de la roue elle-même et <code>roueDentee.Z</code> est le nombre de dents de la roue passée en paramètre. Pour déclarer les roues, nous écrivons : <syntaxhighlight lang="python"> roue1 = pignon() # attribution de la classe, « instanciation » roue1.Z = 13 # définition des caractéristiques du pignon « roue1 » roue1.m = 2 roue2 = pignon(16, 2) # manière alternative </syntaxhighlight> Nous pouvons alors utiliser les objets de la manière suivante : <syntaxhighlight lang="python"> print(roue1.Z) # 13 print(roue1.diametrePrimitif()) # 26 R = roue1.rapport(roue2) # 0.8125 </syntaxhighlight> La commande <code>dir(a)</code> affiche tous les attributs et méthodes de l'objet <code>a</code>. ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/classes.html | titre = Classes | site = Python documentation | consulté le = 2019-03-08 }} == Interface graphique avec Tk == === Généralités === Une interface graphique utilisateur (GUI, ''{{lang|en|graphic user interface}}'') est un ensemble de boîtes permettant d'interagir avec l'utilisateur, c'est-à-dire qui permettent la saisie d'informations, l'exécution d'actions et l'affichage d'informations. L'interface se compose d'éléments appelés ''{{lang|en|widgets}}''. Les éléments ''({{lang|en|widgets}})'' classiques sont : * boîte de dialogue ''({{lang|en|dialog box}})'' : fenêtre contenant d'autres éléments ; * étiquette ''({{lang|en|label}})'' : texte affiché ; * liste déroulante ''({{lang|en|drop-down list}})'' : zone permettant le choix d'une option, la liste se déployant lorsque l'on clique sur la zone ; * zone de texte, champ de saisie ''({{lang|en|text box}})'' : zone permettant de taper du texte ; * boîte combinée ''({{lang|en|combo box}})'' : zone de saisie de texte contenant une liste déroulante qui permet de choisir des éléments prédéfinis ; * bouton ''({{lang|en|button}})'' : objet effectuant une action lorsque l'on clique dessus ; * case à cocher ''({{lang|en|checkbox, tickbox}})'' : objet permettant d'activer ou de désactiver une option lorsque l'on clique dessus ; * bouton radio, case d'option ''({{lang|en|radio button}})'' : objet permettant d'activer une option en désactivant les autres options ; une seule option peut être activée à la fois. === Avec Tk === Plusieurs modules permettent de gérer les interfaces graphiques. Nous choisissons ici le module développé sur la bibliothèque Tk qui est une bibliothèque multiplateforme. Pour cela, nous importons le module <code>tkinter</code> ainsi que le module <code>ttk</code>, ce dernier proposant des options plus « modernes » : <syntaxhighlight lang="python"> import tkinter as tk from tkinter import ttk </syntaxhighlight> Voici un programme permettant comme précédemment de calculer le rapport de transmission d'un engrenage. Nous détaillons sa construction ci-après. <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: IUrapport.set(valeurZ2/valeurZ1) except: IUrapport.set("erreur") # ************************* # ************************* # ** Interface graphique ** # ************************* # ************************* # fenetre principale fenetre = tk.Tk() fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> [[Fichier:Organisation interface Tk Python.svg|vignette|upright=2|Organisation des ''widgets''.]] '''Explications''' Nous commençons par définir la boîte de dialogue que nous appelons <code>fenetre</code> ; c'est un objet <code>Tk</code> et nous lui donnons un titre « » : <syntaxhighlight lang="python"> fenetre = tk.Tk() fenetre.title("Rapport de réduction") </syntaxhighlight> Puis, nous définissons un cadre attaché à cette fenêtre et qui va nous permettre « d'accrocher » les autres éléments, ce qui permet de garder une apparence satisfaisante lorsque l'on retaille la fenêtre : <syntaxhighlight lang="python"> cadre = ttk.Frame(fenetre) </syntaxhighlight> Le cadre va comporter six lignes ''({{lang|en|row}})'' et deux colonnes ''({{lang|en|column}})''. Nous allons placer une étiquette ''({{lang|en|label}})'' « z1 » : <code>text="z1"</code>. Cette étiquette se trouve dans une case du cadre, celle de la première colonne et la première ligne : <code>grid(column=1, row=1)</code>. Par rapport à cette case, elle est collée à « l'ouest » (W, ''{{lang|en|west}}'', gauche) de la case : <code>sticky=tk.W</code>. <syntaxhighlight lang="python"> z1_label = ttk.Label(cadre, text="z1") # Création de l'étiquette z1_label.grid(column=1, row=1, sticky=tk.W) # Placement de l'étiquette </syntaxhighlight> Notez que l'on aurait pu écrire directement : <syntaxhighlight lang="python"> ttk.Label(cadre, text="z1").grid(column=1, row=1, sticky=tk.W) </syntaxhighlight> mais le fait de séparer la création de l'élément et son placement facilite la maintenance (recherche d'erreur, évolution du code). Pour tout ce qui est dynamique, c'est-à-dire les zone de saisie des valeurs et l'affichage du résultat, il faut définir des « chaînes variables » ''({{lang|variable strings}})'' : <syntaxhighlight lang="python"> IUz1 = tk.StringVar() </syntaxhighlight> Cette variable est une variable globale à la création. Nous pouvons alors placer la zone de saisie ''({{lang|en|entry}})'' à côté de l'étiquette lui correspondant. Nous nommons la zone de saisie <code>z1_entry</code> : <syntaxhighlight lang="python"> z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) </syntaxhighlight> Nous faisons de même pour les trois autres paramètres de l'engrenage, ''m''<sub>1</sub>, ''z''<sub>2</sub> et ''m''<sub>2</sub>. Le résultat est également une chaîne variable globale. Par rapport à notre mise en page, elle se situe dans la case colonne 2 ligne 5, centrée sur cette case (collé à l'est et à l'ouest) : <syntaxhighlight lang="python"> rapport = tk.StringVar() rapport_dynamique = ttk.Label(cadre, textvariable=rapport) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) </syntaxhighlight> Il nous faut encore définir une fonction de manière classique, nous l'appelons « calcule ». Les variables étant globales, on les utilise directement. On récupère les valeurs avec la méthode <code>get()</code> et nous modifions la valeur avec la méthode <code>set()</code> : <syntaxhighlight lang="python"> def calcule(): valeurZ1 = float(IUz1.get()) valeurZ2 = float(IUz2.get()) IUrapport.set(valeurZ2/valeurZ1) </syntaxhighlight> Cette fonction est déclenchée lorsque l'on clique sur le bouton « Calcul » situé dans la case du cadre ligne 6 colonne 2 : <syntaxhighlight lang="python"> bouton = ttk.Button(cadre, text="Calcul", command=calcule) bouton.grid(column=2, row=6, sticky=tk.W) </syntaxhighlight> ou bien si l'on appuie sur la touche <code>[entrée]</code> du clavier : <syntaxhighlight lang="python"> fenetre.bind("<Return>", calcule) </syntaxhighlight> À tout ceci, nous ajoutons des « gouttières » (marges, ''{{lang|en|paddings}}'') afin d'espacer les éléments. Il faut ensuite « activer » la fenêtre pour qu'elle s'affiche. La méthode est <code>mainloop()</code> (boucle principale) : « boucle » (elle est active en permanence et attend des actions sur ses éléments), <syntaxhighlight lang="python"> fenetre.mainloop() </syntaxhighlight> Nous avons ci-dessus mis la plupart du code en programme principal. Nous pouvons aussi programmer de manière fonctionnelle, en mettant la plupart du code dans des fonctions ; cependant, pour que la fenêtre et les variables dynamiques soient globales à tout le programme, elles doivent être déclarées dans le programme principal. Nous pouvons aussi mêler la programmation orientée objet. {{boîte déroulante début|Calcul du rapport de transmission en programmation fonctionnelle et orientée objet}} <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # ************* # ************* # ** Classes ** # ************* # ************* class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): """Valeurs des attributs""" # instructions lancées lors de la déclaration self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z # ************************ # ************************ # ** Variables globales ** # ************************ # ************************ # fenetre principale fenetre = tk.Tk() # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: roue1 = pignon(valeurZ1, valeurM1) roue2 = pignon(valeurZ2, valeurM2) IUrapport.set(roue1.rapport(roue2)) except: IUrapport.set("Erreur") # *********************** # * Interface graphique * # *********************** def configureFenetre(): """Configuration de la fenêtre principale""" fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* configureFenetre() # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> {{boîte déroulante fin}} {{voir |{{lien web |url=https://docs.python.org/3/library/tkinter.ttk.html |titre=tkinter.ttk — Tk themed widgets |site=docs.python.org |consulté le=2026-06-11}} }} {{voir |{{lien web |url=https://matplotlib.org/stable/gallery/user_interfaces/embedding_in_tk_sgskip.html |titre=How to embed Matplotlib charts in Tkinter GUI? |site=Matplotlib.org |date=2025-07-15 |consulté le=2026-06-11}} }} === Avec PyQt === Le module PyQt (prononcer \ˈpaɪ.kjut\) permet d'utiliser la bibliothèque Qt dévelopée par Riverbank Computing. Il permet notamment de créer des interfaces graphiques. La communication entre objets Qt se fait par une mécanismes de « signal/emplacement » ''({{lang|en|signal/slot}})''. Un emplacement ''({{lang|en|slot}})'' est une fonction ''({{lang|en|callable}})'' ; un signal est un attribut d'un objet. Si l'attribut signal est défini pour l'emplacement, alors on dit que l'emplacement est relié à un signal. Par exemple, un objet <code>QPushButton</code> dispose du signal <code>clicked</code> qui est émis lorsque l'on clique dessus ; on peut ainsi faire exécuter un emplacement (fonction appelable) <code>action()</code> lorsque l'on clique sur le bouton par le biais du signal <code>clicked</code> : <syntaxhighlight lang="python"> from PyQt5.QtWidgets import QPushButton bouton = QPushButton("Appuies-moi dessus") button.clicked.connect(action()) </syntaxhighlight> {{voir|{{lien web |url=https://www.riverbankcomputing.com/static/Docs/PyQt6/ |titre=Reference guide PyQt6 |site=Riverbank Computing|consulté le=2026-0604}} }} {{...}} == Annotations == Une annotation est un commentaire qui sert à expliciter un type de variable. La syntaxe est différente des commentaires « classiques » : cela permet d'avoir un affichage différent avec les éditeurs de texte ayant une coloration syntaxique, et ces informations peuvent être récupérées par des logiciels extérieurs pour effectuer une documentation automatique ou bien des vérifications de type. Cependant : * comme les commentaires normaux, ils n'ont aucune influence lors de l'exécution du texte ; en particulier : * rien n'oblige à annoter les variables ; * il est possible d'avoir une variable ayant un type différent de son annotation ; le fait de pouvoir définir et changer le type de variable à la volée est une fonctionnalité fondamentale de Python. La syntaxe pour une annotation est : : nom_de_variable + deux-points + espace + type par exemple : <syntaxhighlight lang="python"> a: int </syntaxhighlight> Notez qu'ici, la variable n'est ''pas'' créée. Pour la créer, il faut lui affecter une valeur. Il est possible de l'affecter après ou bien sur la même ligne avec la syntaxe : : nom_de_variable + deux-points + espace + type + espace + égal + espace + valeur par exemple : <syntaxhighlight lang="python"> a: int a = 5 # est équivalent à a: int = 5 </syntaxhighlight> Même si l'annotation n'a pas d'impact sur l'exécution, le type doit être un type existant sinon cela génère une erreur de syntaxe. Les types classiques sont : : <code>int</code> — <code>float</code> — <code>str</code> — <code>bool</code> — <code>list</code> — <code>tuple</code> — <code>dict</code> Il est également possible de mettre une chaîne de caractères : <syntaxhighlight lang="python"> a: "ce que je veux" = 3.1516 </syntaxhighlight> On peut annoter une fonction. Il est possible d'annoter les variables déclarées au sein de la fonction, mais pas les variables globales (puisqu'elle ne sont pas définie au sein de la fonction). On peut aussi annoter : * les variables passées en paramètre, avec la même syntaxe dans les parenthèses ; * annoter le type de la variable de sortie (retournée) en la faisant précéder de <code>-&gt;</code> : <syntaxhighlight lang="python"> def plusCinq(a: float = 0) -> float: return a + 5 </syntaxhighlight> ; Ressources * {{lien web | url = https://www.python.org/dev/peps/pep-0526/ | titre = PEP 526 -- Syntax for Variable Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} * {{lien web | url = https://www.python.org/dev/peps/pep-3107/ | titre = PEP 3107 -- Function Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} == Décorateur == Un décorateur est une fonction qui s'applique à une fonction, à la manière de la composition mathématique ''g'' ∘ ƒ = ''g''(ƒ). Mais cette composition affecte la fonction elle-même ; l'utilisateur appelle la fonction ƒ mais c'est la fonction ''g'' ∘ ƒ qui s'exécute. Cette fonction ''g'' est appelée le décorateur. L'intérêt est de pouvoir modifier une fonction sans modifier le code de la fonction elle-même. Pour appliquer une décoration, il faut : # Déclarer le décorateur : une fonction qui s'applique à une autre fonction. # Affecter le décorateur à la fonction visée : en mettant <code>@''décoration''</code> juste avant la définition de la fonction. Par exemple : <syntaxhighlight lang="python"> def decorateur(f): print("Avant la fonction") f() print("après la fonction") @decorateur def afficheFoo(): print("Foo.") afficheFoo # Avant la fonction # Foo. # Après la fonction </syntaxhighlight> Lorsque l'on appelle <code>afficheFoo</code>, on appelle en fait <code>decorateur(afficheFoo)</code>. Si la fonction à modifier admet des paramètres, il faut définir une fonction enveloppante dans le décorateur. Par exemple, nous définissons ci-dessous un décorateur <code>deuxFois()</code> qui fait s'exécuter deux fois de suite la fonction : <syntaxhighlight lang="python"> def deuxFois(f): def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # conteneurFonction </syntaxhighlight> Nous voyons que l'application du décorateur a modifié le nom de la fonction — pas le nom de la variable qui contient la fonction mais bien son nom « intime ». Pour éviter cela, on utilise la méthode <code>wraps()</code> du module <code>functools</code> : <syntaxhighlight lang="python"> import functools def deuxFois(f): @functools.wraps(f) def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # plusCinq </syntaxhighlight> On peut par exemple utiliser un décorateur pour la mémoïsation. La mémoïsation est une méthode consistant à mémoriser les valeurs d'une fonction au fur et à mesure de son utilisation ; ainsi, si l'on veut évaluer la fonction avec les mêmes entrées, on se contente d'aller chercher la valeur enregistrée ce qui est plus rapide. On sacrifie donc la place mémoire au profit de la rapidité. On peut trouver des décorateurs de mémoïsation aux adresses suivantes : * https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize * https://gist.github.com/robcowie/1357800 ; Ressources : {{lien web | url = https://www.python.org/dev/peps/pep-0318/ | titre = PEP 318 -- Decorators for Functions and Methods | site = Python.org | lang = en | consulté le = 2019-04-05 }} == Manipulation de fichiers == === Importer le contenu d'un fichier === Python possède la fonction <code lang="python">open()</code> qui permet d'ouvrir un fichier. Ouvrir signifie qu'il crée un objet de type <code>file</code> qui possède notamment les méthodes <code lang="python">.read()</code> et <code lang="python">.write()</code>. Il peut s'agir d'un objet de type « fichier binaire » ''({{lang|en|binary file}})'' ou « fichier texte » ''({{lang|en|text file}})''. Si par exemple on veut utiliser (et donc lire) le contenu du fichier texte <code>monfichier.txt</code>, on écrit : <syntaxhighlight lang="python"> fichier = open("monfichier.txt", "rt") … fichier.close() </syntaxhighlight> Le paramètre <code>"rt"</code> signifie que nous ouvrons le fichier en lecture ''({{lang|en|read}})'' et qu'il s'agit d'un objet de type fichier texte. Notons deux choses : * en faisant cela, nous ne faisons qu'associer le fichier à un objet Python, nous n'avons pas encore importé les données ; * si nous ouvrons le fichier, il faut le fermer par la suite ; c'est pourquoi nous utilisons la méthode <code lang="python">.close()</code>. Pour éviter d'avoir à fermer le fichier, nous pouvons l'ouvrir au sein d'un contexte : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: … </syntaxhighlight> Notons aussi que la chaîne de caractères indiquant le nom du fichier peut contenir le chemin d'accès au répertoire (dossier), mais sous Microsoft Windows, il faut utiliser des barres de fractions <code>/</code> pour séparer les sous-répertoires au lieu de la barre inversée habituelle, par exemple : <syntaxhighlight lang="python"> chemin = "C:/Temp/monfichier.txt" with open(chemin, "rt") as fichier: … </syntaxhighlight> Pour mettre les données du fichier dans la variable <code>contenu</code>, nous écrivons donc : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() print(contenu) </syntaxhighlight> et si nous ne voulons lire que les <code>n</code> premiers caractères (<code>n</code> étant un entier), nous utilisons <code lang="python">contenu = fichier.read(n)</code>. Cette lecture est séquentielle, c'est-à-dire que si nous appliquons la méthode plusieurs fois, nous reprenons la lecture là où nous l'avons laissée. Si nous voulons lire une ligne, nous utilisons la méthode <code lang="python">.readline()</code>. La lecture ligne par ligne est également séquentielle. Nous pouvons aussi créer une liste dont chaque élément est une ligne du fichier ; nous utilisons alors la méthode <code lang="python">.readlines()</code> (notez le pluriel). Chaque élément de la liste se termine par le caractère de fin de ligne <code lang="python">\n</code>. Pour l'enlever, nous pouvons utiliser la méthode <code lang="python">.rstrip()</code> pour chaque élément de la liste, par exemple. L'exemple complet est alors : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.readlines() contenu = [item.rstrip() for item in contenu] print(contenu) </syntaxhighlight> === Exporter du contenu vers un fichier === Si nous voulons créer un fichier texte <code>monfichier.txt</code> pour y mettre le contenu de la variable <code>texte</code>, alors nous utilisons : <syntaxhighlight lang="python"> with open("monfichier.txt", "wt") as fichier: fichier.write(texte) </syntaxhighlight> Le module principal important pour la manipulation de fichiers est est <code lang="python">os</code>. === Exploiter le contenu d'un fichier texte === Avec un fichier texte, la méthode <code lang="python">.read()</code> crée une variable de type texte. Nous pouvons séparer cette variable en différentes lignes avec la méthode <code lang="python">.splitlines()</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une ligne. Si maintenant une ligne contient plusieurs données séparées par un séparateur commun, par exemple un espace, nous pouvons séparer les données par la méthode <code lang="python">.split(''séparateur'')</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une donnée. Si par exemple le fichier est du type CSV ''({{lang|en|comma separated values}}'', valeurs séparées par une virgule), l'exploitation du fichier est : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(",") for item in contenu] </syntaxhighlight> La variable <code>contenu</code> est une liste de listes. Pour avoir la ''n''<sup>e</sup> valeurs de la ''m''<sup>e</sup> ligne, on utilise : <syntaxhighlight lang="python"> contenu[m-1][n-1] </syntaxhighlight> Si l'on veut extraire la ligne ''m'' il suffit d'écrire : <syntaxhighlight lang="python"> contenu[m-1] </syntaxhighlight> mais si l'on veut la colonne ''n'', le plus simple est d'utiliser une définition en compréhension : <syntaxhighlight lang="python"> [ligne[n-1] for ligne in contenu] </syntaxhighlight> Dans certains fichiers CSV, les séparateurs de valeurs ne sont pas des virgules, on peut donc utiliser un autre caractère pour le séparateur. Concernant les séparateurs particuliers : * si le séparateur est une tabulation, on utilise <code lang="python">\t</code> : <code lang="python">contenu = [item.split("\t") for item in contenu]</code> ; * si le séparateur est un nombre arbitraire d'espaces et/ou de tabulation, on ne définit aucun séparateur : <code lang="python">contenu = [item.split() for item in contenu]</code>. Si la première ligne contient les en-têtes des colonnes, on peut l'enlever avec la fonction <code lang="python">del()</code> : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() del(contenu[0]) contenu = [item.split(",") for item in contenu] </syntaxhighlight> Certains logiciels créent des fichiers en utilisant le séparateur décimal régional, qui en France est la virgule. Pour remplacer les virgules par des points, on peut utiliser la méthode <code lang="python">.replace()</code>, de préférence ''avant'' de séparer les valeurs : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.replace(",", ".") for item in contenu] # remplace les virgules par des points contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule </syntaxhighlight> en effet, lorsque l'on a séparé les valeurs, on a une liste de liste, il faut alors balayer les sous-listes ce qui prend plus de temps : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule contenu = [[subitem.replace(",", ".") for subitem in item] for item in contenu] # remplace les virgules par des points </syntaxhighlight> '''Exemple complet''' Supposons que l'on ait un fichier texte de la forme : <syntaxhighlight lang="text"> x y z V 0.0 1.5 3.2 8.657 0.4 1.5 3.2 8.392 0.2 1.5 3.2 8.485 ... </syntaxhighlight> C'est un fichier valeurs V associées à des points de coordonnées ''(x, y, z)'' (un champ V sur l'espace, donc). Nous remarquons que seule la coordonnée ''x'' change : les données concernent la droite (''y'' = 1,5 ; ''z'' = 3,2). Nous remarquons aussi que les valeurs de ''x'' ne sont pas classées par ordre croissant ni décroissant. Nous voulons au final avoir une matrice [[''x''], [V]] triée par ''x'' croissant. Pour cela, nous pouvons faire : <syntaxhighlight lang="python"> with open(nomdefichier, "rt") ad fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(" ") for item in contenu contenu = contenu[1:] # élimine la première ligne x = np.array([float(ligne[0]) for ligne in contenu]) V = np.array([float(ligne[3]) for ligne in contenu]) donnees = np.concatenate((x.reshape(-1, 1), V.reshape(-1, 1)), axis=1) # matrice [[x], [V]] ind = np.argsort(donnees[:, 0]) donnees = donnees[ind, :] # matrice triée plt.plot(donnees[:, 0], donnees[:, 1]) </syntaxhighlight> {{note|Pour le tri, voir [[../Manipulation_de_matrices#Fonctions_et_méthodes_de_base|''Manipulation de matrices'' &gt; ''Fonctions et méthodes de base'']].}} === Cas d'un fichier CSV === Si le fichier CSV ne contient que des valeurs numériques, on peut utiliser : <syntaxhighlight lang="python"> valeurs = np.loadtxt(chemin+nomfic, delimiter=",") # si le séparateur est une virgule </syntaxhighlight> Il existe un module <code lang="python">csv</code> dédié aux fichiers CSV. La manipulation du fichier se fait comme suit : <syntaxhighlight lang="python"> import csv with open(chemin+nomfic, "rt") as fichier: lecteur = csv.reader(fichier, delimiter=",") contenu = [ligne for ligne in lecteur] print(contenu) </syntaxhighlight> === Utilisation de Pandas === Pandas<ref>https://pandas.pydata.org/</ref> est un module gérant les tableaux de données, appelés <em lang="en">data frames</em>. Voici quelques commandes utiles : <syntaxhighlight lang="python"> import numpy as np import pandas as pd M = np.random.rand(10, 10) # crée une matrice NumPy aléatoire de dimension 10 × 10 tableau = pd.DataFrame(M) # transforme la matrice en tableau DataFrame tableau.to_csv("tableau.csv") # enregistre le tableau dans un fichier CSV donnees = pd.read_csv("tableau.csv").to_numpy() # lit le fichier et transforme le tableau DataFrame en matrice NumPy </syntaxhighlight> Par défaut, la fonction <code>pd.read_csv()</code> considère que le séparateur est une virgule, et la commande <code>pd.read_table()</code> que c'est une tabulation. On peut définir le séparateur avec le paramètre <code>sep</code> : <syntaxhighlight lang="python"> donnees = pd.read_csv("tableau.csv", sep=";") </syntaxhighlight> On peut utiliser les séparateurs spéciaux : * <code>\t</code> : tabulation ; * <code>\s+</code> : nombre arbitraire d'espaces. On peut par ailleurs utiliser les paramètres suivants : * <code>dialect</code> : syntaxe du fichier, par exemple <code>dialect = "excel"</code> ; * <code>nrows</code> (entier) : nombre de lignes lues ; * <code>skiprows</code> (entier) : nombre de lignes sautées (non lues) en début de fichier ; * <code>header</code> (entier) : numéro de ligne utilisé pour l'en-tête, par exemple <code>header = 0</code> pour la première ligne ; * <code>skip_blank_lines</code> (booléen) : si la valeur est vraie (<code>True</code>), ne lit pas les lignes vide ; sinon, met une valeur <code>nan</code>. Par exemple : <syntaxhighlight lang="python"> donnees1 = pd.read_csv("tableau.csv", nrows=1, sep="\s+").to_numpy() donnees2 = pd.read_csv("tableau.csv", skiprows=3, sep="\s+").to_numpy() </syntaxhighlight> {{voir|{{lien web |url=https://pandas.pydata.org/docs/user_guide/io.html |titre=IO tools (text, CSV, HDF5, …) |site=Pandas |consulté le=2026-05-06}} }} == Exporter un programme Python == Vous pouvez créer un fichier « Python pur » <code>.py</code>. Pour cela, dans le menu <code>fichier/file</code> de Jupyter, choisir <code>télécharger/download</code> au format <code>.py</code> ; le fichier se trouve alors dans le répertoire de téléchargement du navigateur. == Recommandations == Les recommandations de programmation sont générales et ne sont en grande partie pas spécifiques à Python. {{voir|[[Découvrir_Scilab/Programmation#Recommandations]]}} == Ressources == * {{lien web | url = https://www.python.org/dev/peps/pep-0008/ | titre = PEP 8 -- Style Guide for Python Code | site = Python documentation | consulté le = 2019-03-14 }} == Notes et références == {{références}} ---- [[../Fonctions mathématiques générales|Fonctions mathématiques générales]] &lt; [[../|↑]] &gt; [[../Graphiques|Graphiques]] {{DEFAULTSORT:Elements de programmation}} [[Catégorie:Python pour le calcul scientifique (livre)]] m90ad5r1x00u8xae67kjgn1ig76tx5f 768400 768399 2026-06-23T12:25:10Z Cdang 1202 /* Substitution de variables */ 768400 wikitext text/x-wiki Rappel : les programmes commencent par : <syntaxhighlight lang="python"> #!/usr/bin/python3 import numpy as np import matplotlib.pyplot as plt </syntaxhighlight> == Entrées et sorties == Pour permettre à l'utilisateur ou à l'utilisatrice d'entrer une valeur, nous utilisons la fonction <code lang="python">input()</code> comme évoqué précédemment (chapitre ''[[../Premiers programmes|Premiers programmes]]''), avec la syntaxe <code lang="python">''variable'' = input(''texte'')</code>. Notez que la valeur renvoyée par <code lang="python">input()</code> est une chaîne de caractères. Si vous voulez autre chose, typiquement un nombre, il faut convertir cette chaîne. Par exemple, nous demandons ici d'entrer une longueur sous la forme d'une valeur numérique : <syntaxhighlight lang="python"> longueurDefaut = 10.0 texteDemandeLongueur = f"Veuillez entrer la longueur en millimètres (valeur par défaut {longueurDefaut} mm) : " longueur = input(texteDemandeLongueur) if longueur=="": longueur=longueurDefaut else: longueur=float(longueur) print(longueur) </syntaxhighlight> {{voir|https://docs.python.org/3/library/functions.html#input}} Pour afficher un texte, on utilise la fonction <code lang="python">print()</code>, également présentée dans le chapitre ''[[../Premiers programmes|Premiers programmes]]'', avec la syntaxe <code lang="python">print(''texte'')</code>. Le texte à afficher peut être de n'importe quel type (entier, réel en virgule flottante, booléen, chaîne de caractères…). On peut « mélanger » les types en les séparant par des virgules, par exemple <syntaxhighlight lang="python"> print("La longueur vaut : ", longueur, " mm.") </syntaxhighlight> ou bien <syntaxhighlight lang="python"> print("Essai de mélange ", 1, True, 10.0, " insensé.") </syntaxhighlight> Mais si l'on veut faire ça de manière harmonieuse, on a intérêt à tout convertir en chaînes de caractères, avec la fonction <code lang="python">str()</code>, et concaténer les chaînes avec <code lang="python">+</code>. Par exemple : <syntaxhighlight lang="python"> print("La longueur vaut : "+str(longueur)+" mm.") </syntaxhighlight> Nous pouvons aussi utiliser une « chaîne “f” » ''({{lang|en|f-string}})'' : on met un le <code lang="python">f</code> devant le guillemet ouvrant et dans la chaîne, on met un champ sous la forme <code lang="python">{''nomDeVariable''}</code>. L'exemple ci-dessus devient alors : <syntaxhighlight lang="python"> print(f"La longueur vaut : {longueur} mm.") </syntaxhighlight> Les chaînes « f » sont détaillées dans la section ''[[#Chaînes de caractères|Chaînes de caractères]]'' ci-dessous. Si l'on veut introduire un retour à la ligne dans la chaîne, on utilise les caractères <code lang="python">\n</code> (contre-oblique suivie de la lettre N minuscule). Par exemple <syntaxhighlight lang="python"> print("Ceci est un texte\navec un retour à la ligne.") </syntaxhighlight> La commande <code>print()</code> admet les paramètres suivants (nous indiquons la valeur par défaut= : * <code>end = "\n"</code> : détermine la fin de ligne ; on peut mettre <code>end = ""</code> si l'on ne veut pas de retour de ligne, ou bien <code>end = "\r"</code> ''({{lang|en|return}})'' si l'on veut revenir au début de la ligne pou repasser par-dessus ; * <code>sep = " "</code> : séparateur des différents objets. {{voir|https://docs.python.org/3/library/functions.html#print}} Si vous voulez passer un argument directement au script Python, vous pouvez utiliser le module <code>sys</code>. L'argument est alors contenu dans la variable <code>sys.argv[1]</code> ; la variable <code>sys.argv[0]</code> contient le nom du scirpt lui-même. Par exemple <syntaxhighlight lang="python"> import sys print("Script : ", sys.argv[0]) print("Entrée : ", sys.argv[1]) </syntaxhighlight> Si vous exécutez le script depuis une console (fenêtre de commande), le nom du fichier de script étant <code>monscript.py</code> : <syntaxhighlight lang="text"> $ python monscript.py blabla Script : monscript.py Entrée : blabla $_ </syntaxhighlight> == Types de variables == === Généralités === Python définit « tout seul » le type de la variable : « <code>3</code> » sera un entier ''({{lang|en|integer}})'', « <code>3.0</code> » sera un réel à virgule flottante ''({{lang|en|float}})'', « <code>"3"</code> » sera une chaîne de caractères ''({{lang|en|string}})''. On peut connaître le type d'une variable avec la fonction <code>type()</code>. On peut tester certaines valeurs, avec le module <code>NumPy</code> : * <code>np.isnan(x)</code> indique si les valeurs de ''x'' sont des NaN ''({{lang|en|not a number}})'' ; si ''x'' est une matrice, le résultat est une matrice de booléens, l'élément [''i'', ''j''] est <code>True</code> si <code>x[i, j]</code> est un NaN ; * <code>np.isinf(x)</code> indique si les valeurs de ''x'' sont ±∞ ; si ''x'' est une matrice, le résultat est une matrice booléenne de même dimension. On peut forcer un type : * <code>int(x)</code> : transforme la valeur ''x'' en nombre entier ; * <code>long(x)</code> : " en entier long (précision illimitée) ; * <code>float(x)</code> : " en nombre réel à virgule flottante ; * <code>str(x)</code> : " en chaîne de caractères ; * <code>complex(Re, Im)</code> : crée le nombre complexe ''Re'' + ''Im''·j, j désignant la racine carrée de –1 ; * <code>list()</code> : crée une liste ; * <code>tuple()</code> : crée un n-uplet. Par exemple <syntaxhighlight lang="python"> type(3) # <class 'int'> type(float(3)) # <class 'float'> complex(1, 1) == 1 + 1j # True list("blabla") # ['b', 'l', 'a', 'b', 'l', 'a'] </syntaxhighlight> Python distingue plusieurs genres de types : * Un itérable est un objet dont on peut extraire les éléments un par un ; ce sont les objets pour lesquels on peut écrire <code> for i in ''iterable'':</code>. Il s'agit essentiellement des listes, n-uplets, chaînes de caractères, ensembles, dictionnaires et fichiers. * Un modifiable ''({{lang|en|mutable}})'' est un objet que l'on peut modifier ; par exemple une liste est modifiable — on peut changer la valeur d'un élément, en ajouter ou en enlever un — mais les n-uplets non, pas plus qu'une chaîne de caractères ou un nombre. * Un identifiable (''{{lang|en|hashable}}'', le ''{{lang|en|hashage}}'' étant une signature caractéristique d'un objet) : objet possédant un identifiant unique. Un objet identifiable est toujours non-modifiable ''({{lang|en|unmutable}})''. === Types numériques === ==== Entiers ==== Nous pouvons définir les entiers au format octal ou hexadécimal : il faut débuter le nombre par respectivement <code>0o</code> (le chiffre zéro et la lettre o) et <code>0x</code> (le chiffre zéro et la lettre x). À l'inverse, la fonction <code>hex()</code> renvoie une chaîne correspondant à l'écriture d'un entier au format hexadécimal, et <code>oct()</code> renvoie la chaîne correspondant à l'éciture en octal. Par exemple : <syntaxhighlight lang="python"> print(0o10, ";", 0x10) # 8 ; 16 print(hex(20)) # 0x14 </syntaxhighlight> ==== Réels ==== Les réels disposent de fonctions spécifiques appelées « méthodes ». Une méthode est une fonction spécifique à un type d'objets. Étant conçue ''ad hoc'', elle est souvent plus économe en ressource et en temps qu'une fonction générique. Pour appliquer la méthode <code>meth()</code> à la variable <code>x</code>, on écrit : <code>x.meth()</code>. Nous avons déjà présenté la méthode <code>''float''.as_integer_ratio()</code> qui donne la fraction réduite égale à la valeur du nombre. Les réels disposent de plusieurs autres méthodes : * <code>''float''.is_integer()</code> : indique si le nombre est un entier (<code>true</code> dans ce cas-là, <code>False</code> sinon) ; * <code>''float''.from_number(''x'')</code> : transforme le nombre ''x'' en un réel (permet de convertir un entier en réel) ; * <code>''float''.hex()</code> : renvoie une chaîne de caractères correspondant à l'écriture du nombre en hexadécimal ; * <code>''float''.fromhex(''c'')</code> : transforme une chaîne de caractères, correspondant à l'écriture d'un nombre en hexadécimal, en un nombre réel correspondant. Par exemple : <syntaxhighlight lang="python"> a = 20. print(a.hex()) # 0x1.4000000000000p+4 print(10..hex()) # 0x1.4000000000000p+3 </syntaxhighlight> Dans le deuxième exemple, nous appliquons la méthode <code>''float''.hex()</code> directement au nombre <code>10.</code> ; le point est obligatoire car sinon, c'est un entier, pour lequel la méthode n'est pas définie. On aurait pu aussi écrire <code>print(10.0.hex())</code>. Notez que la ''méthode'' <code>''float''.hex()</code> est différentes de la ''fonction'' <code>hex()</code> : la première concerne les réels, la seconde les entiers. ==== Complexes ==== Nous avons déjà mentionné la méthode <code>''complex''.conjugate()</code> qui donne le conjugué du nombre. Un nombre complexe dispose de deux attributs : * <code>''complex''.real</code> : sa partie réelle ; * <code> ''complex''.imag</code> : sa partie imaginaire. Par exemple : <syntaxhighlight lang = "python"> a = 5+2j print(a.conjugate(), ";", a.real, ";", a.imag) # (5-2j) ; 5.0 ; 2.0 </syntaxhighlight> === Chaînes de caractères === ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/inputoutput.html | titre = 7. Input and Output | site = Python Documentation | consulté le = 2019-04-06 }} : {{lien web | url = https://docs.python.org/3/library/string.html | titre = <code>string</code> — Common string operations | site = Python Documentation | consulté le = 2026-06-05 }} ==== Généralités ==== Il existe en fait trois manières de définir une chaîne de caractères : * avec des guillemets simples ou doubles comme vu précédemment : <code>"…"</code> ou bien <code>'…'</code> ; * avec trois guillemets doubles : <code>"""…"""</code> : cela permet d'avoir une chaîne de caractères s'étendant sur plusieurs lignes, les retours de ligne étant pris en compte ; c'est utilisé en particulier pour la description des fonctions (''{{lang|en|docstrings}}'', voir ci-après) ; * avec des guillemets précédés d'un « r », <code>r"…"</code> ou <code>r'…'</code> : cela permet d'interpréter les barres de fraction inverses « \ » comme un caractère « normal » et non comme un caractère d'échappement (voir ci-après) ; cela est utile lorsque l'on utilise les possibilités LaTeX dans le tracé de graphiques (voir plus loin) ; * avec des guillemets précédés d'un « f », <code>f"…"</code> ou <code>f'…'</code> : cela permet d'utiliser des variables formatées (voir ci-après). Une chaîne de caractères n'est pas modifiable. Si l'on veut remplacer un caractère, l'insérer ou le supprimer, il faut transformer la chaîne en liste, avec la commande <code>list()</code>, puis rassembler la liste en la joignant ''({{lang|en|join}})'' à une chaîne vide : <syntaxhighlight lang="python"> chaine = "blabla" chaineList = list(chaine) chaineList[2] = "c" chaine = "".join(chaineList) print(chaine) # blcbla </syntaxhighlight> Dans une chaîne simple <code>"…"</code> ou <code>'…'</code>, on peut introduire un retour à la ligne avec <code>\n</code>. Chaque caractère possède un code ''({{lang|en|code point}})'' définit par la norme Unicode ''({{lang|en|Unicode code point}})''. Pour afficher le caractère correspondant à un code, on utilise <code>chr()</code>. Pour afficher le code correspondant à un caractère, on utilise <code>ord()</code> <syntaxhighlight lang="python"> print(ord("a")) # 97 print(hex(ord("a"))) # 0x61 print(chr(97)) # a print(chr(0x61)) # a </syntaxhighlight> ==== Substitution de variables ==== Lorsque l'on veut utiliser des variables, on fait précéder les guillemets d'un « f » et l'on écrit les noms de variables entre accolades ; on parle de « chaîne f » ''(f-string)''. Par exemple : <syntaxhighlight lang="python"> monde = "world" chaine = f"Hello {monde}!" print(chaine) # Hello world! </syntaxhighlight> On peut indiquer la taille de la chaîne générée à partir de la variable sous la forme <code>{nomVariable:taille}</code>, la taille étant un entier. Par exemple : <syntaxhighlight lang="python"> chiffre1 = 1 nom1 = "un" chiffre2 = 2 nom2 = "deux" chaine = f"{nom1:5} : {chiffre1:5d}\n{nom2:5} : {chiffre2:5d}" print(chaine) # un : 1 # deux : 2 </syntaxhighlight> Vous remarquez que l'on ajoute un « d » pour les entiers décimaux, et que les nombres sont alignés à droite. Si le nombre est un nombre réel à virgule flottante ''({{lang|en|float}})'', on peut indiquer le nombre de décimales sous la forme <code>.''n''f</code> : <syntaxhighlight lang="python"> chaine = f"{np.pi:.5f}" print(chaine) # 3.15169 </syntaxhighlight> Avec la syntaxe <code>''m''.''n''f</code>, on indique également que la totalité du nombre doit occuper ''m'' caractères. Pour un nombre en notation scientifique (exponentielle), on utilise <code>.''n''e</code>. Pour convertir un nombre en caractère Unicode correspondant, on utilise la lettre c : <syntaxhighlight lang="python"> nompi = 0x03c0 # Caractère Unicode π : U+03C0 chaine = f"{nompi:c} = {np.pi:.5f}" print(chaine) # π = 3.14159 </syntaxhighlight> Notez que dans le cas de nombres, la mise en forme marche aussi si l'on écrit directement le nombre dans l'accolade (au lieu d'une variable). Le tiret de soulignement « <code>_</code> » (''underscore'', tiret du 8) permet de séparer les chiffres avant le séparateur décimal par groupe de trois chiffres séparés du tiret ; la virgule « <code>,</code> » les sépare d'une virgule. <syntaxhighlight lang="python"> print(f"{1e6:_}, {1e6:,}") # 1_000_000.0, 1,000,000.0 </syntaxhighlight> La classe ''str'' dispose également de la méthode <code>.format()</code>. On indique un n-uplet de chaînes (ou de nombres) à la méthode et l'on met des accolades dans la chaîne principale ; les accolades sont remplacées dans l'ordre des chaînes de la méthode. On peut changer l'ordre en indiquant quelle valeur utiliser dans quelle accolade. Par exemple : <syntaxhighlight lang="python"> chaine1 = "On compte {} puis {}".format(1, 2) chaine2 = "On compte {0} puis {1}. Mais à rebours, on compte {1} puis {0}.".format("un", "deux") print(chaine1, "\n", chaine2) # On compte 1 puis 2 # On compte un puis deux. Mais à rebours, on compte deux puis un. </syntaxhighlight> L'utilisation du caractère pourcent « % » permet d'utiliser la mise en forme <code>sprintf()</code> du langage C : <syntaxhighlight lang="python"> chaine = "π = %.5f" % np.pi print(chaine) # π = 3.14159 </syntaxhighlight> ; Exemple <nowiki>:</nowikI> barre de progression : Voici une fonction affichant une barre de progression, pour la ''i''-ème étape d'un processus ayant ''n'' étapes (pour la notion de fonction, voir la section ci-après ''[[#Fonction|Fonction]]''). : NB : nous avons utilisé les codes Unicode pour l'exemple, mais on peut évidemment copier le caractère, par exemple depuis une table Unicode ou une page Web<ref>Pour le point médian : ''{{W|Table des caractères Unicode/U0080}}'' ou ''{{W|Point médian}}''. Pour le pavé : ''{{W|Table des caractères Unicode/U2580}}''.</ref>, et le coller dans le code, comme nous l'avons fait dans le commentaire. <syntaxhighlight lang="Python"> def barre_progression(i, n, largeur=40): """ Affiche une barre de progression Entrées : — i : étape en cours, entier ; — n : nombre d'étapes à réaliser, entier ; — largeur : nombre de caractères total de la barre, entier. Sortie : affichage de la barre de progression. """ taux = i/n fait = int(largeur * taux) barre = f"{0x2588:c}" * fait + f"{0x00b7:c}" * (largeur - fait) # U+2588 : pavé "█" ; U+00B7 : point médian "·" print(f"Progression | {barre} | {100*taux:3.1f} %", end="\r") barre_progression(25, 100) # Progression | ██████████······························ | 25.0 % </syntaxhighlight> ==== Méthodes des chaînes ==== Le type ''str'' dispose d'un certain nombre de méthodes. Nous avons déjà vu les méthodes <code>''str''.join()</code> et <code>''str''.format()</code>, en voici quelques autres : * <code>''str''.capitalize()</code> : met le premier caractère en capitale (majuscule) et les autres en minuscule ; * <code>''str''.lower()</code> : met tout en minuscules ''({{lang|en|lowercase}})'' ; * <code>''str''.upper()</code> : met tout en capitales ''({{lang|en|lowercase}})'' ; * <code>''str''.center(''n'')</code> : met la chaîne au centre d'une chaîne de longueur ''n'', en complétant avec des espaces ; on peut compléter avec d'autres caractères avec <code>''str''.center(''n'', ''c'')</code>, par exemple <code>"a".center(7, ".")</code> donne <code>"....a...."</code> ; * <code>''str''.ljust(''n'', ''c'')</code> et <code>''str''.rjust(''n'', ''c'')</code> : comme <code>.center()</code> mais la chaîne est respectivement alignée au fer à gauche ''({{lang|en|left}})'' et à droite ''({{lang|en|right}})'' ; * <code>''str''.isdigit()</code> : booléen vrai si tous les caractères sont des nombres ; * <code>''str''.find(''sous-chaine'')</code>, <code>''str''.rfind(''sous-chaine'')</code> : indique respectivement le premier emplacement et le dernier emplacement de la sous-chaîne dans la chaîne, ou bien <code>-1</code> si la sous-chaîne est absente ; * <code>''str''.partition(''séparateur'')</code> : retourne un triplet avec la portion de chaîne avant le séparateur, le séparateur puis la portion de chaîne après le séparateur ; * <code>''str''.replace(''ancien'', ''nouveau'')</code> : remplace la chaîne ''ancien'' par la chaîne ''nouveau'' dans la chaîne ; * <code>''str''.split(''séparateur'')</code> : découpe la chaîne au niveau des séparateurs et renvoie une liste. ==== Autres fonctions ==== La fonction <code>chr()</code> transforme un code Unicode en caractère. Par exemple, <code>chr(97)</code> donne <code>"a"</code> et <code>chr(0x03c0)</code> donne <code>"π"</code>. Si on veut créer une liste de caractères qui se suivent, on peut par exemple utiliser : <syntaxhighlight lang="python"> [chr(x) for x in range(97, 102)] # ['a', 'b', 'c', 'd', 'e'] </syntaxhighlight> Si on veut créer une liste de nombres sous la forme de chaînes de caractères, on peut utiliser la commande <code>str()</code> vue ci-dessus. Par exemple : <syntaxhighlight lang="python"> [str(x) for x in range(1, 6)] # ['1', '2', '3', '4', '5'] </syntaxhighlight> Pour la syntaxe, voir ci-dessous la section [[#Définition en compréhension|''Définition en compréhension'']]. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = chr(0x2588) * fait + chr(0x00b7) * (largeur - fait) # U+2588 : bloc ; U+00B7 : point médian </syntaxhighlight> Rappel : le module <code>html</code> permet d'utiliser les entités HTML : <syntaxhighlight lang="python"> import html … print(html.entities.html5["alpha;"]+html.entities.html5["middot;"]) # α· </syntaxhighlight> L'entité HTML <code>&xxx;</code> s'obtient par <code>html.entities.html5["xxx;"]</code>, donc en enlevant la perluète ; mais cela ne fonctionne pas avec les codes Unicode. Pour cela, on peut utiliser la commande <code>html.unescape()</code>. Ainsi, dans l'exemple de la barre de progression ci-dessus, on peut utiliser la solution suivante pour constituer la barre : <syntaxhighlight lang="python"> barre = html.unescape("&#x2588;") * fait + html.entities.html5["middot;"] * (largeur - fait) # U+2588 : bloc ; middot : point médian </syntaxhighlight> ou bien <syntaxhighlight lang="python"> barre = barre = html.unescape("&#x2588;" * fait + "&middot;" * (largeur - fait)) # U+2588 : bloc ; middot : point médian </syntaxhighlight> La commande <code>html.unescape()</code> interprète donc une chaîne complète, par exemple <syntaxhighlight lang="python"> print(html.unescape("L'esperluette est le caractère &laquo;&nbsp;&amp;&nbsp;&raquo;.")) # L'esperluette est le caractère « & ». </syntaxhighlight> == Manipulation de listes == Les listes sont une structure de données fondamentale en Python. ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/datastructures.html | langue = en | titre = 5. Data structures | site = Python documentation | consulté le = 2019-03-16 }} === Copie d'une liste === Contrairement à d'autres types, lorsque vos écrivez <code>b = a</code> avec des listes, vous ne créez pas une copie de la variable <code>a</code>, vous créez un ''alias'' : l'objet <code>b</code> est un autre nom de l'objet <code>a</code>. En particulier, si vous modifiez <code>b</code>, vous modifiez en fait <code>a</code>. Par exemple : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a b[2] = 5 print(a, b) # [1, 2, 5, 4] [1, 2, 5, 4] </syntaxhighlight> Si l'on veut créer une copie de <code>a</code>, il faut utiliser <code>a[:]</code> ou bien <code>a.copy()</code> : <syntaxhighlight lang="python"> a = [1, 2, 3, 4] b = a[:] c = a.copy() b[2] = 5 c[2] = 6 print(a, b, c) # [1, 2, 3, 4] [1, 2, 5, 4] [1, 2, 6, 4] </syntaxhighlight> === Méthodes de listes === Pour modifier une liste, vous disposez des méthodes suivantes : * <code>a.append(x)</code> : ajoute l'élément <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.extend(x)</code> : ajoute la liste <code>x</code> à la fin de la liste <code>a</code> ; * <code>a.append(i, x)</code> : aoute l'élément <code>x</code> ''avant'' l'interstice ''i'' de la liste <code>a</code> ; * <code> x = a.pop(i)</code> : enlève l'élément ''i'' de la liste <code>a</code> et le met dans la variable <code>x</code> ; <code> x = a.pop()</code> enlève le dernier élément de la liste ; * <code>a.clear()</code> : vide la liste <code>a</code> ; * <code>a.sort()</code> : trie la liste par ordre croissant ; * <code>a.sort(reverse = True)</code> : trie par ordre décroissant ; * <code>a.reverse()</code> : inverse l'ordre de <code>a</code>. Pour supprimer l'élément à l'indice ''i'', au lieu d'utiliser <code>a.pop(i)</code>, on peut aussi utiliser <syntaxhighlight lang="python"> del(a[i]) </syntaxhighlight> Pour trier une liste, on peut aussi utiliser la fonction <code>sorted()</code>, ce qui permet par exemple de conserver la liste originale, non triée : <code>b = sorted(a)</code>. La fonction <code>sorted()</code> fonctionne avec tous les objets « itérables » comme par exemple une chaîne de caractères : <syntaxhighlight lang="python"> a = "ahjbfk" print(sorted(a)) # ['a', 'b', 'f', 'h', 'j', 'k'] </syntaxhighlight> Pour mettre en évidence la performance de la méthode <code>''list''.sort()</code> par rapport à la fonction générique <code>sorted()</code> : <syntaxhighlight lang="python"> import numpy as np import time a = np.random.rand(int(1e7)) t1 = time.perf_counter() b = sorted(a) # Fonction générique t2 = time.perf_counter() a.sort() # Méthode spécifique t3 = time.perf_counter() print("Sorted :", t2-t1, " s ; .sort :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # Sorted : 14.2... s ; .sort : 1.1... s ; rapport : 12.6... </syntaxhighlight> Par rapport à une valeur donnée : * <code>a.remove(x)</code> : retire la première occurrence de la valeur <code>x</code> de la liste <code>a</code> ; * <code>a.index(x)</code> : indique l'indice où se trouve la première occurrence de la valeur <code>x</code> ; * <code>a.count(x)</code> : indique le nombre de fois que l'on trouve la valeur <code>x</code> dans la liste <code>a</code>. === Définition en compréhension === La [[w:fr:Liste en compréhension|définition en compréhension]] ''({{lang|en|list comprehension}})'' est une méthode permettant de construire des listes en indiquant simplement des axiomes, des consignes de filtrage. Cette méthode est élégante car proche de la notation mathématique et compacte, mais c'est une méthode itérative donc lente par rapport à une méthode vectorisée fournie par le module NumPy. Par exemple, pour créer la liste des carrés des nombres entiers entre 0 et 9, il suffit d'écrire <syntaxhighlight lang="python"> carre = [x**2 for x in range(10)] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x^2 | x \in [0 ; 9] \}</math>. Si l'on veut la liste des nombres strictement inférieurs à 20 dont le carré est supérieur à 10, on peut écrire : <syntaxhighlight lang="python"> X = [x for x in range(20) if x**2 > 10] </syntaxhighlight> ce qui se rapproche de la notation d'ensemble <math>\{x | x \in [0 ; 19], x^2 > 10 \}</math>. Pour mettre en évidence la performance du calcul vectorisé par rapport à la méthode itérative : <syntaxhighlight lang="python"> import time import numpy as np n = int(1e7) # taille de la liste t1 = time.perf_counter() carre = [x**2 for x in range(n)] # Définition en compréhension t2 = time.perf_counter() carre2 = np.arange(n)**2 # Calcul vectorisé t3 = time.perf_counter() print("En compréhension : ", t2-t1, "s ; vectorisé :", t3-t2, "s ; rapport :", (t2-t1)/(t3-t2)) # En compréhension : 4.515... s ; vectorisé : 0.156... s ; rapport : 28.982... </syntaxhighlight> == Structure d'un programme == Un programme est simplement une suite d'instructions. Dans les environnements Unix BSD, un programme Python peut être considéré comme un script c'est-à-dire qu'il suffit de taper son nom dans l'invite de commande ''({{lang|en|shell}})'' sans avoir à invoquer <code>python</code>. Le programme doit alors commencer par un en-tête normalisé surnommé ''{{lang|en|[[wikt:shebang|shebang]]}}'' : <syntaxhighlight lang="python"> #!/usr/bin/env python3 </syntaxhighlight> Ce ''{{lang|en|shebang}}'' est inutile avec Jupyter. L'en-tête peut également contenir la description de l'encodage du fichier texte, typiquement : <syntaxhighlight lang="python"> # coding: utf-8 </syntaxhighlight> Le codage UTF-8 est le codage par défaut pour Python 3, il est donc inutile de l'indiquer. Les commentaires sont introduits par le croisillon <code>#</code>. On peut grouper une suite d'instructions dans un bloc. Un bloc d'instructions commence par deux-points « <code>:</code> » et est identé, c'est-à-dire qu'il a une marge constituée de quatre espaces — on peut aussi utiliser une tabulation mais il ne faut pas mélanger les deux méthodes ; les tabulations sont déconseillées, il vaut mieux utiliser quatre espaces<ref>{{lien web | url = https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces | titre = Tabs or Spaces? | site = Python documentation | consulté le = 2019-03-14 }}</ref>. Pour terminer le bloc, il suffit simplement de revenir en début de ligne ; contrairement à d'autres langages, il n'y a pas de commende de fin ''({{lang|en|end}})'', c'est l'indentation qui définit le bloc. : # début du bloc ''instruction 1'' ''instruction 2'' … ''dernière instruction du bloc'' ''instruction hors bloc'' Par exemple, une exécution conditionnelle <code>if</code> ou une boucle <code>for</code> exécute un bloc d'instruction. Si l'on a besoin d'un bloc d'instruction qui « ne fait rien », on utilise l'instruction <code>pass</code>. == Structures de contrôle == '''Boucle itérative''' La boucle itérative s'écrit : <syntaxhighlight lang="python"> for <variable> in <itérable>: <bloc d’instructions> </syntaxhighlight> Si l'on veut que la variable prenne ''n'' valeurs de 0 à ''n'' – 1, on utilise l'instruction <code>range()</code> : <syntaxhighlight lang="python"> for i in range(5): print(i) print("Fin de la boucle") </syntaxhighlight> <code>[▶]</code> 0 1 2 3 4 Fin de la boucle En fait, la commande <code>range()</code> extrait des valeurs de l'ensemble des nombres entiers ; on peut ainsi utiliser le découpage en tranches, par exemple <code>range(2, 5)</code>pour avoir la « liste » <code>[2, 3, 4]</code>. Notez que <code>range()</code> ne crée pas à proprement parler une liste, cela crée un objet de type ''« {{lang|en|range}} »'' (plage, intervalle) ; pour avoir une liste, il faut écrire <code>list(range(n))</code>. Dans une boucle, la commande <code>continue()</code> saute la fin du bloc d'instruction et passe à la valeur suivante de la boucle. La commande <code>break()</code> interrompt la boucle et passe à la suite. '''Exécution conditionnelle''' L'exécution conditionnelle s'écrit : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> </syntaxhighlight> On peut utiliser les commandes <code>elif</code> ''(else if'') et <code>else</code> : <syntaxhighlight lang="python"> if <booléen>: <bloc d’instructions> elif <booléen>: <bloc d’instructions> else: <bloc d’instructions> </syntaxhighlight> Notez que le test d'une condition est gourmand en ressources. S'il s'agit de savoir si l'on effectue une opération mathématique simple ou pas, on peut remplacer le test par une multiplication par un booléen (<code>True</code> vaut 1, <code>False</code> vaut 0). Par exemple, plutôt que d'écrire <syntaxhighlight lang="python"> if a > 0: b = b - c </syntaxhighlight> mieux vaut écrire : <syntaxhighlight lang="python"> b = b - (a > 0)*c </syntaxhighlight> '''Boucle antéconditionnée''' La boucle antéconditionnée s'écrit : <syntaxhighlight lang="python"> while <booléen>: <bloc d’instructions> </syntaxhighlight> Cette boucle peut contenir des instructions <code>continue()</code> et <code>break()</code>. == Fonction == La déclaration d'une fonction utilise la commande <code>def</code>. La fonction est un bloc d'instructions. Si elle doit renvoyer des valeurs, on utilise la commande <code>return</code>. Par exemple <syntaxhighlight lang="python"> def nombres(n): """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo a = nombres(3) print(a) </syntaxhighlight> La fonction commence par une chaîne de caractères qui la décrit. Cette chaîne peut être récupérée automatiquement par certains logiciels pour faire une documentation automatique. Si la description prend plusieurs lignes, elle commence et finit par trois double-guillemets <code>"""…"""</code> ; en fait, par convention, même si cela n'est pas obligatoire, les descriptions sont toutes encadrées de trois double-guillemets. Cette description est appelée ''{{lang|en|docstring (documentation string)}}''. Pour récupérer les ''{{lang|en|docstrings}}'' : <syntaxhighlight lang="python"> def foo(): """Cette fonction ne fait rien""" pass print(foo.__doc__) # Cette fonction ne fait rien </syntaxhighlight> L'instruction <code>input()</code> permet à l'utilisateur de saisir une valeur. La valeur est retournée sous la forme d'une chaîne de caractères qui est ensuite convertie en nombre réel avec l'instruction <code>float()</code>. On peut définir une valeur par défaut en l'indiquant dans l'en-tête de la définition de la fonction, de la manière suivante : <syntaxhighlight lang="python"> def nombres(n=1): # valeur par défaut : 1 """But : Entrer plusieurs nombres Entrée : n, entier : quantité de nombre à saisir. Sortie : foo : liste de n réels. """ # description de la fonction foo = [] # initialisation for i in range(n): foo = foo+[float(input("Entrez un nombre"))] return foo </syntaxhighlight> Si le paramètre à initialiser est de type modifiable ''({{lang|en|mutable}})'', comme par exemple une liste, il faut procéder comme suit : <syntaxhighlight lang="python"> def fooFonction(fooListe=None): # valeur par défaut : n'existe pas """Description""" if fooListe = None: fooListe = [] # initialisation <suite des instructions> </syntaxhighlight> Par défaut, les variables sont locales. On peut rendre une variable globale avec l'instruction <code>global</code> ''à l'intérieur de la fonction'', avant l'utilisation de la variable. Par exemple : <syntaxhighlight lang="python"> a = 1 b = 1 def toto(): """Test de variable globale. Entrée : aucune. Sortie : aucune.""" global a a = 2 b = 2 toto() print("a =", a, "; b =", b) # a = 2 ; b = 1 </syntaxhighlight> Pour être plus précis : si une variable n'est pas assignée dans une fonction, alors Python va chercher une variable du même nom à l'extérieur de la fonction. Mais à partir du moment où la variable est assignée dans la fonction, elle devient locale ''sauf'' si l'on a utilisé l'instruction <code>global</code>. Si l'on s'attend à un nombre indéfini d'arguments, on utilise la notion d'empaquetage/dépaquetage ''({{lang|en|packing/unpacking}})''<ref>{{lien web | url = https://deusyss.developpez.com/tutoriels/Python/args_kwargs/ | titre = Introduction à *args et **kwargs | consulté le = 2019-03-09 | site = Developpez.com }}.</ref>. L'empaquetage consiste à mettre les arguments dans un n-uplet, le dépaquetage consiste à développer un n-uplet en plusieurs variables. Cela se fait en mettant un astérisque ''({{lang|en|splat}})'' « <code>*</code> » devant le nom de la variable. Par convention, on utilise le nom de variable <code>*args</code> mais cela n'est pas obligatoire. <syntaxhighlight lang="python"> def concatenation(*args): """Concatène des chaînes de caractères Entrée : *args, n-uplet de chaînes de caractères. Sortie : resultat, chaîne de caractères.""" resultat = "" for i in args: resultat = resultat + i return resultat concatenation("a", "foo", "toto") # 'afoototo' </syntaxhighlight> À l'inverse, si une fonction doit recevoir plusieurs paramètres, on peut à la place lui transmettre une liste à dépaqueter : <syntaxhighlight lang="python"> def addition(a, b): """Ajoute deux nombres Entrées : — a : réel ; — b : réel. Sortie : a+b, réel""" return a+b arg = (1, 2) addition(*arg) # 3 </syntaxhighlight> On peut aussi empaqueter/dépaqueter un dictionnaire, on utilise pour cela deux astérisques « <code>**</code> ». Par convention, on utilise le nom <code>**kwargs</code> sans que cela soit obligatoire. L'instruction <code>lambda</code> permet de créer de petites fonctions ne contenant pas de boucle ni de branchement conditionnel. Cependant, si la déclaration est courte et compacte, le code n'est pas toujours facilement lisible ; l'utilisation de cette instruction n'est pas recommandée. Par exemple l'expression <syntaxhighlight lang="python"> f = lambda x: 2*x </syntaxhighlight> est la même chose que <syntaxhighlight lang="python"> def f(x): """Calcule le double. Entrée : x, réel. Sortie : 2*x, réel.""" return 2*x </syntaxhighlight> {{note|L'instruction <code>eval()</code> exécute une chaîne de caractères, c'est-à-dire traite une chaîne de caractères comme si c'étaient des instructions données à Python. Cette instruction est à éviter pour deux raisons : # Un utilisateur malveillant pourrait entrer du code malveillant dans la chaîne de caractères. # L'exécution est lente puisque Python doit compiler la chaîne à la volée. Cette instruction peut en général être remplacée par une autre instruction. }} == Gestion des erreurs == Dans un bloc d'instructions, on peut utiliser la structure <code>try:… except:</code>. Le bloc après <code>try</code> est exécuté ; si une erreur se déclare dans ce bloc, alors le bloc <code>except</code> s'exécute. Par exemple <syntaxhighlight lang="python"> try: 1/0 # Génère une erreur except: print("Division par zéro") # Cette instruction est donc exécutée </syntaxhighlight> On peut compléter avec <code>else:</code> et <code>finally:</code> : <syntaxhighlight lang="python"> try: <code à exécuter> except: <s’exécute en cas d’erreur> else: <s’exécute s’il n’y a pas d’erreur> finally: <s’exécute dans tous les cas> </syntaxhighlight> On peut séparer les différents types d'erreur : <syntaxhighlight lang="python"> try: <code à exécuter> except ValueError: print("Valeur erronée") except TypeError: print("Type erroné") </syntaxhighlight> Les types d'erreur les plus courants sont : * <code>NameError</code> : le nom de variable n'existe pas ; * <code>TypeError</code> : la valeur n'est pas du bon type ; * <code>ValueError</code> : la valeur n'est pas compatible avec ce qui est attendu ; * <code>RuntimeError</code> : type d'erreur général. On peut aussi créer ses propres erreurs : si une situation erronée survient, on peut « lever » une exception avec <code>raise</code>. Par exemple <syntaxhighlight lang="python"> if a < 0: raise ValueError("La valeur doit être positive") </syntaxhighlight> ; Ressources * {{lien web | url = https://docs.python.org/3/tutorial/errors.html | titre = Errors and exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} * {{lien web | url = https://docs.python.org/3/library/exceptions.html | titre = Built-in Exceptions | lang = en | site = Python documentation | consulté le = 2019-03-12 }} == Exercices == === Calcul du PGCD et du PPCM par l'algorithme d'Euclide === {{loupe|w:Algorithme d'Euclide}} Écrire un programme Python qui demande deux nombres entiers et affiche leurs PGCD et PPCM. Le programme utilisera l'algorithme d'Euclide. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """Programme : euclide.py Auteur : User:cdang date : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : calcule le PGCD et le PPCM de deux nombres entiers. Entrée ------ au clavier, saisie de deux nombres entiers. Sorties ------- à l'écran, affichage du PGCD et du PPCM. """ # *************** # *************** # ** Fonctions ** # *************** # *************** def euclide(): """Calcule le PGCD et le PPCM avec l'algorithme d'Elclide Entrée ------ Aucune, la saisie des paramètres fait partie de la fonction Sortie ------ affichage du PGCD et du PPCM """ print("***** Algorithme d'Euclide *****\n") a0 = int(input("Premier nombre entier : a = ")) b0 = int(input("Second nombre entier : b = ")) a = a0 b = b0 r = a%b # initialisation while (r != 0) : # algorithme d'Euclide a = b b = r r = a%b # affichage des résultats print("PGCD(", a0, ", ", b0, ") = ", b) print("PPCM(", a0, ", ", b0, ") = ", a0*b0//b) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* euclide() </syntaxhighlight> On peut simplifier la boucle centrale : <syntaxhighlight lang="python"> while b: # s'exécute tant que b n'est pas 0 a, b = b, a % b # affectation de liste à liste return a </syntaxhighlight> {{boîte déroulante fin}} Notez que le module NumPy propose l'instruction <code>gcd()</code> : <syntaxhighlight lang="python"> import numpy … print(numpy.gcd(a, b)) </syntaxhighlight> === Tours de Hanoï === {{loupe|w:Tours de Hanoï}} Écrire un programme Python qui demande le nombre ''n'' de plateaux et affiche les manipulations nécessaires pour déplacer la pile d'un emplacement à un autre. Le programme utilisera l'algorithme récursif. {{boîte déroulante début|solution}} <syntaxhighlight lang="python"> """nom : hanoi.py auteur : User:cdang date de création : 2019-02-19 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : aucun ---------------------------------------------------------------------------- Objectif : résout le problème des tours de Hanoï Entrées ------- trois chaînes de caractères (nom des piliers) Sorties ------- une chaîne de caractères (liste des opérations) """ # *************** # *************** # ** Fonctions ** # *************** # *************** def hanoi(a, b, c, n): """Résout le problème des tours de Hanoï de manière récursive But : déplace la pile de n disques du piler a au pilier b Entrées ------- a, b c : chaînes de 1 caractère, référence des emplacements ; n : entier, nombre de disques sur l'emplacement a Sorties ------- operations : chaînes de caractères décrivant les opérations """" if n>1: operations = hanoi(a, c, b, n-1) operations = operations+a+"→"+b+" ; " operations = operations+hanoi(c, b, a, n-1) else: operations = a+"→"+b+" ; " return operations # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* resultat = hanoi("1", "2", "3", 3) print(resultat) </syntaxhighlight> {{boîte déroulante fin}} === Lancer de rayons === [[Fichier:Lentille hemispherique perspective.svg|vignette|Lentille hémisphérique.]] Considérons une lentille hémisphérique de rayon R faite d’un verre d’indice de réfraction ''n''. Nous plaçons une source ponctuelle à une distance ''d'' du dioptre plan, sur l’axe optique. Tracer des rayons partant de la source et traversant la lentille. {{clear}} {{Boîte déroulante/début |titre=Analyse d’optique géométrique}} [[Fichier:Lentille hemispherique analyse geometrique.svg|vignette|Analyse géométrique du problème.]] Il s’agit d’un problème ayant une symétrie de révolution par rapport à l’axe optique. Nous pouvons nous réduire à un problème plan en nous plaçant dans un plan contenant l’axe optique ; l’axe optique est encore un axe de symétrie orthogonale, nous pouvons donc nous contenter d'étudier un demi-plan. Pour simplifier, nous plaçons le centre du dioptre sphérique à l’origine O du repère. L’axe optique est l’axe ''x'' et l'axe perpendiculaire, vertical sur la figure, c’est l’axe ''y''. Les coordonnées de la source sont donc (-''d'' ; 0). Le rayon issu de la source et faisant un angle θ avec l’axe ''x'' frappe le dioptre plan à l’altitude ''h''. Nous avons : : ''h'' = ''d'' ⋅ tan θ. L’angle d’incidence vaut θ. D’après la loi de Snell-Descartes, l'angle de réfraction θ<sub>2</sub> vaut : : θ<sub>2</sub> = arcsin((sin θ) / ''n''). Le rayon réfracté passe par le points de coordonnées (0, ''h''). L’équation de la droite est donc : : ''y'' = a ⋅ ''x'' + ''h'' avec : ''a'' = tan θ<sub>2</sub>. L’équation du cercle de centre O et de rayon R est : : ''x''<sup>2</sup> + ''y''<sup>2</sup> = R<sup>2</sup>. Les coordonnées (''x''<sub>M</sub>, ''y''<sub>M</sub>) de l’intersection M du rayon avec le dioptre sphérique vérifient les deux équations. Par substitution, nous obtenons une équation du second degré en ''x'' que nous savons résoudre : : ''x''<sub>M</sub><sup>2</sup> + (''a'' ⋅ ''x''<sub>M</sub> + ''h'')<sup>2</sup> = R<sup>2</sup> : ⇔ (1 + ''a''<sup>2</sup>) ⋅ ''x''<sub>M</sub><sup>2</sup> + 2 ⋅ ''a'' ⋅ ''h'' ⋅ ''x''<sub>M</sub> + ''h''<sup>2</sup> – R<sup>2</sup> = 0. D’après les propriétés du cercle, le rayon est perpendiculaire à la tangente. Le rayon [OM] est donc normal au dioptre en M. Nous pouvons déterminer l’angle d’incidence θ<sub>i</sub> par le produit scalaire : : <math>\begin{pmatrix} 1 \\ a \end{pmatrix} \cdot \begin{pmatrix} x_\mathrm{M} \\ y_\mathrm{M} \end{pmatrix} = \sqrt{1^2 + a^2} \cdot \mathrm{R} \cdot \cos(\theta_\mathrm{i})</math> ce qui nous permet de calculer cet angle : : <math>\theta_\mathrm{i} = \operatorname{arcos} \left ( \frac{x_\mathrm{M} + a \cdot y_\mathrm{M}}{\mathrm{R} \cdot \sqrt{1^2 + a^2} } \right )</math> Comme nous passons vers un milieu d’indice plus faible, il y a un risque de réflexion totale. L’angle limite est : : θ<sub>max</sub> = arcsin(1/''n''). Si l’on a θ<sub>i</sub> &gt; θ<sub>max</sub>, le rayon repart vers l’intérieur. Nous ne traçons pas le rayon car cela nous emmènerait trop loin dans l’analyse. En revanche, si θ<sub>i</sub> ≤ θ<sub>max</sub>, alors nous pouvons appliquer la loi de Snell-Descartes pour avoir l’angle de réfraction θ<sub>e</sub> : : θ<sub>e</sub> = arcsin(''n'' ⋅ sin θ<sub>i</sub>). Pour tracer le rayon sortant, il nous faut l’angle θ<sub>3</sub> par rapport à l’horizontale. L’angle du rayon [OM] par rapport à l’horizontal vaut arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>), nous avons donc : θ<sub>3</sub> = arctan(''y''<sub>M</sub> / ''x''<sub>M</sub>) + θ<sub>e</sub>. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Analyse algorithmique}} '''Structure des données''' Le problème est décrit par trois paramètres : # Le rayon <code>R1</code> de la lentille, en milliètres (réel en virgule flottante). # L’indice du verre, <code>n</code> sans dimension (réel en virgule flottante). L’indice de l’air vaut 1. # La distance de la source au dioptre d’entrée plan, <code>d</code> en millimètres (réel en virgule flottante). Un rayon est caractérisé par quatre paramètres : # L’angle d’émission <code>theta1</code> en radians (réel en virgule flottante). # L’angle de réfraction dans la lentille <code>theta2</code> en radians (réel en virgule flottante). # Les cordonnées <code>M</code> en millimètre (vecteur de dimension 2 <code>([x, y])</code> de réels en virgule flottante) du point d’intersection du rayon avec le dioptre sphérique. # L’angle de réfraction dans l’air après la lentille <code>theta3</code> en radians (réel en virgule flottante). Pour le calcul et le tracé, nous avons besoin des paramètres intermédiaires suivants : * l’altitude ''y'' = <code>h</code> en millimètres (réel en virgule flottante) à laquelle le rayon frappe le dioptre plan d’entrée ; * l’angle d’incidence du rayon avec le dioptre sphérique <code>thetaint</code> en radians (réel en virgule flottante). Les angles sont stockés en radians car c’est l’unité naturelle pour le calcul mais nous affichons les valeurs en degrés. Comme le calcul de conversion est récurrent, nous conservons les facteurs <code>degversrad</code> (conversion des degrés vers les radians, facteur valant π/180, réel en virgule flottante) et <code>radversdeg</code> (conversion des radians vers les degrés, facteur valant 180/π, réel en virgule flottante). '''Fonctions''' Nous avons besoin d’une fonction qui calcule les trois paramètres du rayon <code>(theta2, M, theta3)</code> à partir de l’angle d’émission <code>theta1</code>. Nous appelons cette fonction <code>lanceRayon()</code>. Cette fonction fait appelle à une fonction qui calcule l’angle du rayon réfracté à partir de l’angle du rayon incident <code>theta1</code>, les deux angles étant par rapport à la normale au dioptre au point considéré. Nous appelons cette fonction <code>refrac()</code>. La recherche de l’intersection <code>M</code> du rayon avec le dioptre sphérique nécessite de résoudre une équation du second degré. Nous utilisons pour cela la recherche des racines du polynôme en <code>x</code> avec la fonction <code lang="python">numpy.polynomial.polynomial.polyroots()</code>. D’après la configuration du problème géométrique, si l’on s’assure que le rayon frappe bien la lentille (0 ≤ <code>h</code> ≤ <code>R1</code>) alors nous sommes sûrs que le problème a deux solutions réelles (une positive et une négative) ou, dans le cas dégénéré où <code>h == R1</code>, une valeur unique <code>x == 0</code>. Comme nous recherchons la valeur positive, nous sélectionons la plus grande des deux racines. Pour la gestion de la réflexion interne : dans la fonction <code>refrac()</code>, nous vérifions les conditions de réflexion totale et si elles sont remplies, alors nous générons une erreur (commandes <code lang="python">try… except</code> et <code lang="python">raise ValueError</code>). Cette erreur est propagée à la fonction <code>lanceRayon()</code> : <code>lanceRayon()</code> appelle la fonction <code>refrac()</code> et si cette fonction renvoie une erreur, alors <code>lanceRayon()</code> renvoie également une erreur. Pour trouver l’angle d’émission <code>thetaLimite</code> provoquant la réflexion totale (en radians, réel en virgule flottante), nous effectuons une recherche par dichotomie : * nous partons de l’angle maximum possible, lorsque le rayon frappe le sommet de la lentille, et nous appelons la fonction <code>lanceRayon()</code> ; si cela ne génère pas d’erreur, alors nous pouvons aller jusqu’à cette valeur, la recherche est terminée ; si cela génère une erreur, alors nous divisons la valeur par deux ; * à une étape de la recherche donnée, si <code>lanceRayon()</code> ne génère pas d’erreur avec l’angle testé, alors nous savons que l’angle limite est supérieur à cette valeur ; cette valeur minore donc la valeur recherchée ; si au contraire <code>lanceRayon()</code> génère une erreur, alors c’est que l’angle est trop important, cette valeur majore donc la valeur recherchée ; nous pouvons ainsi resserer l’intervalle de recherche ; * nous nous arrêtons lorsque les valeurs haute et basse sont suffisamment proche. Concrètement : # Nous définissons une variable <code>angleHaut</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus bas connu provoquant la réflexion totale. # Nous définissons une variable <code>angleBas</code> angle en radians, réel en virgule flottante) qui est l’angle d’émission le plus haut connu ne provoquant pas de réflexion totale. Sa valeur initiale est 0. L’angle limite recherché est donc entre <code>angleBas</code> et <code>angleHaut</code>. # Nous définissons l’angle <code>angleTest</code> comme étant la moyenne entre <code>angleBas</code> et <code>angleHaut</code>. Si <code>lanceRayon(angleTest)</code> génère une erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleHaut</code> (puisque c’est une valeur provoquant la réflexion totale et qu’elle est plus basse que la valeur actuelle d’<code>angleHaut</code>). À l’inverse, si <code>lanceRayon(angleTest)</code> ne génère pas d’erreur, alors <code>angleTest</code> est la nouvelle valeur d’<code>angleBas</code> (puisque c’est une valeur ne provoquant pas la réflexion totale et qu’elle est plus haute que la valeur actuelle d’<code>angleBas</code>). # Nous arrêtons la procédure lorsque l’écart entre <code>angleBas</code> et <code>angleHaut</code> est inférieur à {{unité|10|échelle=<sup>–3</sup>|rad}} (valeur arbitraire). La valeur retenue est la valeur finale d’<code>angleBas</code> (puisque l’on veut être sûr qu’il n’y ait pas de réflexion totale). La valeur affichée est la valeur en degrés arrondie au dixième. {{Boîte déroulante/fin}} {{Boîte déroulante/début |titre=Solution}} Nous demandons à l’utilisateur ou à l’utilisatrice les valeurs des paramètres du problème : rayon de la lentille, distance de la source, indice de réfraction du verre. Nous vérifions que les valeurs entrées sont bien des nombres ; si c’est une chaîne vide, alors nous utilisons une valeur par défaut. Nous créons une fonction <code>refrac()</code> qui permet de calculer l’angle réfracté à partir de l’angle d’incidence et des indices de réfraction. S’il y a rélexion totale, alors nous générons une erreur. La fonction <code>lanceRayon()</code> calcule les différents points de passage du rayon. Elle appelle pour cela la fonction <code>refrac()</code>. Si un appel de la commande <code>refrac()</code> génère une erreur, alors nous générons également une erreur. Nous déterminons l’angle d’émision du rayon <code>thetaLimite</code> qui provoque une réflecxion totale. Pour cela, nous créons une fonction <code>rechercheLimite()</code> qui cherche par dichotomie. Nous traçons un rayon tous les 5° jusqu’à la valeur limite. <syntaxhighlight lang="python"> #!/usr/bin/env python3 # coding: utf-8 """nom : lancerRayons.py auteur : User:cdang date de création : 2022-05-06 dates de modification : ---------------------------------------------------------------------------- version de Python : 3 module requis : NumPy, matplotlib ---------------------------------------------------------------------------- Objectif : trace des trajets optique avec une lentille hémisphérique Entrées ------- Le rayon de la lentille, la distance de la source, l’indice de réfraction du verre, trois chaînes de caractères saisies par l’utilisateur·rice et qui sont converties en réels. Sorties ------- La valeur limite de l’angle (réel) et le tracé de plusieurs rayons. """ # ****************************************************** # ****************************************************** # ** Lancer de rayons pour une lentille hémisphérique ** # ****************************************************** # ****************************************************** import numpy as np import matplotlib.pyplot as plt import numpy.polynomial.polynomial as nppol # ************** # * Constantes * # ************** # Pour la conversion degrés ↔ radians radversdeg = 180/np.pi degversrad = 1/radversdeg # ************* # * Fonctions * # ************* def boucleEntreeNombre(messageSaisie, valeurDefaut): """Permet de s’assurer que l’utilisateur·rice a bien entré un nombre. Entrée : — message à afficher (chaîne de caractères) ; — valeur par défaut (réel à virgule flottante). Sortie : nombre (réel à virgule flottante).""" messageErreur = "Veuillez entrer une valeur numérique (ou vide pour accepter la valeur par défaut).\n" execute = True while execute: strNombre = input(messageSaisie+f" (valeur par défaut {valeurDefaut}) : ") if strNombre == "": nombre = valeurDefaut execute = False else: try: nombre = float(strNombre) except: print(messageErreur) else: execute = False return nombre def initialisation(): """L’utilisateur·rice entre les variables du problème. Entrées : aucune. Sorties : — R1 (mm) : rayon de la lentille ; — d (mm) : distance de la source au dioptre plan ; — n (sans dimension) : indice de réfraction du verre.""" R1 = boucleEntreeNombre("Rayon de la lentille en mm", 20.0) d = boucleEntreeNombre("Distance de la source au dioptre plan en mm", 20.0) n = boucleEntreeNombre("Indice de réfraction (sans dimension)", 1.5) return (R1, d, n) def refrac(n1, n2, theta1): """Calcule l’angle de réfraction theta2 (radians) en fonction — de l’angle d’incidence theta1 (radians); — de l’indice de réfraction n1 du premier milieu ; — de l’indice de réfraction n2 du second milieu.""" reflexionTotale=False rapport=n2/n1 rapportinv=np.reciprocal(rapport) if n1 > n2: thetal = np.arcsin(rapport) # angle limite pour la réflexion totale if theta1 >= thetal: reflexionTotale=True if reflexionTotale: print("Réflexion totale") raise ValueError else: return np.arcsin(rapportinv*np.sin(theta1)) def lanceRayon(n1, n2, d, R, theta1): """Détermine le rayon issu de la source située à une distance d (mm) du bareau et avec une élévation de theta1 (radians), en fonction des indices de réfraction n1 et n2. Les éléments retournés sont : — la hauteur h (mm) à laquelle le rayon frappe le barreau ; — l’angle de réfraction theta2 (radians)) dans le barreau ; — l’angle de réfraction theta3 (radians) à la sortie du barreau — le point M(x, y) (mm) auquel le rayon sort du barreau.""" h = d*np.tan(theta1) if h >= R: print("Le rayon est au-dessus du barreau") raise ValueError else: theta2 = refrac(n1, n2, theta1) a = np.tan(theta2) x = max(nppol.polyroots([h*h - R*R, 2*a*h, 1+a*a])) # recherche de l’intersection du rayon avec le cercle y = a*x + h M = np.array([x, y]) thetaint = np.arccos((x + a*y)/(R*np.sqrt(1 + a*a))) theta3 = np.arctan(y/x) - refrac(n2, n1, thetaint) return (h, theta2, theta3, M) def rechercheLimite(n1, n2, d, R): """Recherche l’angle limite pour la réflexion totale. Entrée : — indice de réfraction des milieux 1 et 2, n1 et n2 ; — distance au barreau, d(mm). Sortie : angle limite theta (radians)""" angleHaut = np.arctan(R/d) angleBas = 0 angleTest = angleHaut try: lanceRayon(n1, n2, d, angleTest, R) except: condition = True # il y a réflexion total en haut de la lentille else: condition = False # il n’y a jamais réflexion totale dans la lentille while condition: #dichotomie angleTest = np.mean([angleHaut, angleBas]) # on ajuste la valeur de test try: lanceRayon(n1, n2, d, R, angleTest) except: angleHaut = angleTest # réflexion totale : on abaisse la valeur maximale else: angleBas = angleTest # pas de réflexion totale : on monte la valeur minimale condition = ((angleHaut - angleBas) >= 0.001) # on a cerné la limite à 0,001 rad près if not condition: angleTest = angleBas return angleTest # *********************** # * Programme principal * # *********************** (R1, d, n) = initialisation() xmax = round(R1 + d) thetaLimite = rechercheLimite(1, n, d, R1) thetaLimiteDeg = thetaLimite*radversdeg print(f"Angle limite pour la réflexion totale : {thetaLimiteDeg:.1f}°.\n") anglesDeg = np.arange(0, thetaLimiteDeg, 5)[1:] # trace un rayon tous les 5° anglesRad = anglesDeg*degversrad nb = len(anglesDeg) h = np.zeros(nb) # initialisation des vecteurs de valeurs theta2 = np.zeros(nb) theta3 = np.zeros(nb) M = np.zeros((nb, 2)) for i in range(nb): (h[i], theta2[i], theta3[i], M[i, :]) = lanceRayon(1, n, d, R1, anglesRad[i]) (h_lim, theta2_lim, theta3_lim, M_lim) = lanceRayon(1, n, d, R1, thetaLimite) # tracé anglesCercle = 0.5*np.pi*(np.linspace(1, 0, 20)) x_cercle = R1*np.cos(anglesCercle) # coordonnées des pints du cercle y_cercle = R1*np.sin(anglesCercle) fig = plt.plot([-d,xmax], [0, 0], "k-.", linewidth="0.5") # tracé de l’axe optique for i in range(nb): plt.plot([-d, 0, M[i, 0], xmax], [0, h[i], M[i, 1], M[i, 1] + (xmax - M[i, 0])*np.tan(theta3[i])], label=f"{anglesDeg[i]:.0f}°") plt.plot([-d, 0, M_lim[0], xmax], [0, h_lim, M_lim[1], M_lim[1] + (xmax - M_lim[0])*np.tan(theta3_lim)], label=f"{0.1*int(np.trunc(10*thetaLimite*radversdeg)):.1f}°") plt.plot(x_cercle, y_cercle, "k", linewidth="0.5") # tracé du cercle plt.plot([0,0], [0, R1], "k", linewidth="0.5") # tracé du premier dioptre #plt.axis("square") plt.gca().set_aspect("equal", adjustable="box") plt.xlabel("x (mm)") plt.ylabel("y (mm)") plt.title("Lentille hémisphérique, lancer de rayons") plt.legend() plt.savefig("lentille_hemispherique_lancer_rayon.svg", format="svg") plt.show() </syntaxhighlight> {{Boîte déroulante/fin}} == Mesurer le temps == Le module <code>time</code> fournit les fonctions suivantes : * <code>time.gmtime()</code> : renvoie la date et l'heure du méridien de Greenwich (''{{lang|en|Greenwich mean time}}'', GMT), sous la forme d'un dictionnaire (année, mois, jour du mois, heure, minute, seconde, jour de la semaine, jour de l'année, heure d'été/hiver), ** jour de la semaine est un entier entre 0 (lundi) et 6 (dimanche), ** jour du mois est un entier entre 1 et 366 ; * <code>time.localtime()</code> : comme le précédent, mais l'heure est l'heure locale ; * <code>time.time()</code> : donne le nombre de seconde qui se sont écoulées depuis le 1er janvier 1970 ; * <code>time.gmtime(n)</code> et <code>time.localtime(n)</code> transforment un nombre de secondes (écoulées depuis le 1er janvier 1970) en une date au format (année, mois, jour, etc.), n-uplet de neuf valeurs ; <code>time.mktime()</code> fait le contraire, il transforme un n-uplet de neuf valeurs (années, mois, jour, etc.) en un nombre de secondes (écoulées depuis le 1er janvier 1970) ; * <code>time.sleep(n)</code> : provoque une pause dans le déroulement du programme de ''n'' secondes ; * <code>time.perf_counter()</code> : indique une date en seconde ; s'utilise pour mesurer la durée d'exécution d'une partie du code, en faisant la différence entre deux relevés. Concernant la date et l'heure sous la forme d'un n-uplet, on peut extraire l'heure de la manière suivante : <syntaxhighlight lang="python"> import time a = time.localtime() print("Il est ", a[3], "h", a[4]) # ou bien print("Il est ", a.tm_hour, "h", a.tm_min) </syntaxhighlight> Pour mesurer la performance d'une portion de code : <syntaxhighlight lang="python"> import time t1 = time.perf_counter() <suite d’instructions> t2 = time.perf_counter() print("Durée d'exécution :", t2-t1 </syntaxhighlight> == Programmation orientée objet == Nous n'allons pas ici faire un cours de programmation orientée objet (POO), nous allons aborder le sujet de manière pragmatique. De manière schématique, un « objet » est une « super-variable ». Cette super-variable peut contenir plusieurs variables, appelées « attributs » ; elle contient en fait un dictionnaire (paires « nom d'attribut : valeur d'attribut »). Elle peut aussi contenir des fonctions spécifiques appelées « méthodes ». De même qu'une variable a un type, un objet fait partie d'une « classe ». La classe est le modèle de l'objet ; en franglais informatique, on dit que l'objet est une instance de la classe. La POO est donc un formalisme : lorsque l'on définit des variables et des fonctions concernant un même type d'objet (au sens commun du terme), on les empaquette dans une classe. Il faut donc d'abord définir la classe, puis attribuer cette classe à un objet (« instancier » la classe). Considérons par exemple que nous voulons travailler sur des [[w:Engrenage|engrenages]] ; pour simplifier, nous nous contentons d'engrenages à dentures droites. Une roue dentée, un pignon, est essentiellement définie par son nombre de dents Z et par son module ''m'' qui correspond à la largeur de dents<ref>ainsi que par son épaisseur ''e'' et le matériau dont elle est faite mais nous allons négliger ces paramètres pour la simplicité de l'étude.</ref>. Nous allons définir trois méthodes : la méthode <code>.diametrePrimitif()</code> qui calcule le diamètre primitif de la roue dentée, <code>.pas()</code> qui calcule la largeur des dents au niveau du cercle primitif et <code>.rapport()</code> qui calcule le rapport de transmission de deux roues engrenées Z<sub>1</sub>/Z<sub>2</sub>. La méthode <code>.rapport()</code> vérifie par ailleurs que les roues ont le même module, condition indispensable pour former un engrenage. Nous définissons la classe ainsi : <syntaxhighlight lang="python"> class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): # instructions lancées lors de la déclaration """Valeurs des attributs""" self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z </syntaxhighlight> Nous remarquons que lorsque nous déclarons les méthodes, le paramètre <code>self</code> correspond à l'objet lui-même. Ainsi, dans la méthode <code>.rapport()</code>, la variable <code>self.Z</code> est le nombre de dents de la roue elle-même et <code>roueDentee.Z</code> est le nombre de dents de la roue passée en paramètre. Pour déclarer les roues, nous écrivons : <syntaxhighlight lang="python"> roue1 = pignon() # attribution de la classe, « instanciation » roue1.Z = 13 # définition des caractéristiques du pignon « roue1 » roue1.m = 2 roue2 = pignon(16, 2) # manière alternative </syntaxhighlight> Nous pouvons alors utiliser les objets de la manière suivante : <syntaxhighlight lang="python"> print(roue1.Z) # 13 print(roue1.diametrePrimitif()) # 26 R = roue1.rapport(roue2) # 0.8125 </syntaxhighlight> La commande <code>dir(a)</code> affiche tous les attributs et méthodes de l'objet <code>a</code>. ; Ressources : {{lien web | url = https://docs.python.org/3/tutorial/classes.html | titre = Classes | site = Python documentation | consulté le = 2019-03-08 }} == Interface graphique avec Tk == === Généralités === Une interface graphique utilisateur (GUI, ''{{lang|en|graphic user interface}}'') est un ensemble de boîtes permettant d'interagir avec l'utilisateur, c'est-à-dire qui permettent la saisie d'informations, l'exécution d'actions et l'affichage d'informations. L'interface se compose d'éléments appelés ''{{lang|en|widgets}}''. Les éléments ''({{lang|en|widgets}})'' classiques sont : * boîte de dialogue ''({{lang|en|dialog box}})'' : fenêtre contenant d'autres éléments ; * étiquette ''({{lang|en|label}})'' : texte affiché ; * liste déroulante ''({{lang|en|drop-down list}})'' : zone permettant le choix d'une option, la liste se déployant lorsque l'on clique sur la zone ; * zone de texte, champ de saisie ''({{lang|en|text box}})'' : zone permettant de taper du texte ; * boîte combinée ''({{lang|en|combo box}})'' : zone de saisie de texte contenant une liste déroulante qui permet de choisir des éléments prédéfinis ; * bouton ''({{lang|en|button}})'' : objet effectuant une action lorsque l'on clique dessus ; * case à cocher ''({{lang|en|checkbox, tickbox}})'' : objet permettant d'activer ou de désactiver une option lorsque l'on clique dessus ; * bouton radio, case d'option ''({{lang|en|radio button}})'' : objet permettant d'activer une option en désactivant les autres options ; une seule option peut être activée à la fois. === Avec Tk === Plusieurs modules permettent de gérer les interfaces graphiques. Nous choisissons ici le module développé sur la bibliothèque Tk qui est une bibliothèque multiplateforme. Pour cela, nous importons le module <code>tkinter</code> ainsi que le module <code>ttk</code>, ce dernier proposant des options plus « modernes » : <syntaxhighlight lang="python"> import tkinter as tk from tkinter import ttk </syntaxhighlight> Voici un programme permettant comme précédemment de calculer le rapport de transmission d'un engrenage. Nous détaillons sa construction ci-après. <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: IUrapport.set(valeurZ2/valeurZ1) except: IUrapport.set("erreur") # ************************* # ************************* # ** Interface graphique ** # ************************* # ************************* # fenetre principale fenetre = tk.Tk() fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> [[Fichier:Organisation interface Tk Python.svg|vignette|upright=2|Organisation des ''widgets''.]] '''Explications''' Nous commençons par définir la boîte de dialogue que nous appelons <code>fenetre</code> ; c'est un objet <code>Tk</code> et nous lui donnons un titre « » : <syntaxhighlight lang="python"> fenetre = tk.Tk() fenetre.title("Rapport de réduction") </syntaxhighlight> Puis, nous définissons un cadre attaché à cette fenêtre et qui va nous permettre « d'accrocher » les autres éléments, ce qui permet de garder une apparence satisfaisante lorsque l'on retaille la fenêtre : <syntaxhighlight lang="python"> cadre = ttk.Frame(fenetre) </syntaxhighlight> Le cadre va comporter six lignes ''({{lang|en|row}})'' et deux colonnes ''({{lang|en|column}})''. Nous allons placer une étiquette ''({{lang|en|label}})'' « z1 » : <code>text="z1"</code>. Cette étiquette se trouve dans une case du cadre, celle de la première colonne et la première ligne : <code>grid(column=1, row=1)</code>. Par rapport à cette case, elle est collée à « l'ouest » (W, ''{{lang|en|west}}'', gauche) de la case : <code>sticky=tk.W</code>. <syntaxhighlight lang="python"> z1_label = ttk.Label(cadre, text="z1") # Création de l'étiquette z1_label.grid(column=1, row=1, sticky=tk.W) # Placement de l'étiquette </syntaxhighlight> Notez que l'on aurait pu écrire directement : <syntaxhighlight lang="python"> ttk.Label(cadre, text="z1").grid(column=1, row=1, sticky=tk.W) </syntaxhighlight> mais le fait de séparer la création de l'élément et son placement facilite la maintenance (recherche d'erreur, évolution du code). Pour tout ce qui est dynamique, c'est-à-dire les zone de saisie des valeurs et l'affichage du résultat, il faut définir des « chaînes variables » ''({{lang|variable strings}})'' : <syntaxhighlight lang="python"> IUz1 = tk.StringVar() </syntaxhighlight> Cette variable est une variable globale à la création. Nous pouvons alors placer la zone de saisie ''({{lang|en|entry}})'' à côté de l'étiquette lui correspondant. Nous nommons la zone de saisie <code>z1_entry</code> : <syntaxhighlight lang="python"> z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) </syntaxhighlight> Nous faisons de même pour les trois autres paramètres de l'engrenage, ''m''<sub>1</sub>, ''z''<sub>2</sub> et ''m''<sub>2</sub>. Le résultat est également une chaîne variable globale. Par rapport à notre mise en page, elle se situe dans la case colonne 2 ligne 5, centrée sur cette case (collé à l'est et à l'ouest) : <syntaxhighlight lang="python"> rapport = tk.StringVar() rapport_dynamique = ttk.Label(cadre, textvariable=rapport) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) </syntaxhighlight> Il nous faut encore définir une fonction de manière classique, nous l'appelons « calcule ». Les variables étant globales, on les utilise directement. On récupère les valeurs avec la méthode <code>get()</code> et nous modifions la valeur avec la méthode <code>set()</code> : <syntaxhighlight lang="python"> def calcule(): valeurZ1 = float(IUz1.get()) valeurZ2 = float(IUz2.get()) IUrapport.set(valeurZ2/valeurZ1) </syntaxhighlight> Cette fonction est déclenchée lorsque l'on clique sur le bouton « Calcul » situé dans la case du cadre ligne 6 colonne 2 : <syntaxhighlight lang="python"> bouton = ttk.Button(cadre, text="Calcul", command=calcule) bouton.grid(column=2, row=6, sticky=tk.W) </syntaxhighlight> ou bien si l'on appuie sur la touche <code>[entrée]</code> du clavier : <syntaxhighlight lang="python"> fenetre.bind("<Return>", calcule) </syntaxhighlight> À tout ceci, nous ajoutons des « gouttières » (marges, ''{{lang|en|paddings}}'') afin d'espacer les éléments. Il faut ensuite « activer » la fenêtre pour qu'elle s'affiche. La méthode est <code>mainloop()</code> (boucle principale) : « boucle » (elle est active en permanence et attend des actions sur ses éléments), <syntaxhighlight lang="python"> fenetre.mainloop() </syntaxhighlight> Nous avons ci-dessus mis la plupart du code en programme principal. Nous pouvons aussi programmer de manière fonctionnelle, en mettant la plupart du code dans des fonctions ; cependant, pour que la fenêtre et les variables dynamiques soient globales à tout le programme, elles doivent être déclarées dans le programme principal. Nous pouvons aussi mêler la programmation orientée objet. {{boîte déroulante début|Calcul du rapport de transmission en programmation fonctionnelle et orientée objet}} <syntaxhighlight lang="python"> # référence : https://tkdocs.com/tutorial/firstexample.html import tkinter as tk from tkinter import ttk # ************* # ************* # ** Classes ** # ************* # ************* class pignon: """roue dentée""" # explication de la classe pi = 3.141592653589793 # pour calculer le pas def __init__(self, Z=13, m=0.06): """Valeurs des attributs""" # instructions lancées lors de la déclaration self.Z = Z # nombre de dents self.m = m # module def diametrePrimitif(self): """Calcule le diamètre primitif""" return self.m*self.Z def pas(self): """Calcule le pas""" return self.pi*self.m def rapport(roueDentee, self): """Calcule le rapport de transmission""" if roueDentee.m != self.m: # gestion de l'erreur raise ValueError("Les pignons doivent avoir le même module") else: return roueDentee.Z/self.Z # ************************ # ************************ # ** Variables globales ** # ************************ # ************************ # fenetre principale fenetre = tk.Tk() # Paramètres du système (variables) IUz1 = tk.StringVar() IUm1 = tk.StringVar() IUz2 = tk.StringVar() IUm2 = tk.StringVar() IUrapport = tk.StringVar() # *************** # *************** # ** Fonctions ** # *************** # *************** def calcule(*args): """Calcule le rapport de transmission d'un engrenage""" try: valeurZ1 = float(IUz1.get()) valeurM1 = float(IUm1.get()) valeurZ2 = float(IUz2.get()) valeurM2 = float(IUm2.get()) if valeurM1 != valeurM2: IUrapport.set("Erreur de module") else: roue1 = pignon(valeurZ1, valeurM1) roue2 = pignon(valeurZ2, valeurM2) IUrapport.set(roue1.rapport(roue2)) except: IUrapport.set("Erreur") # *********************** # * Interface graphique * # *********************** def configureFenetre(): """Configuration de la fenêtre principale""" fenetre.title("Rapport de réduction") # élément (widget) cadre contenant tout le reste cadre = ttk.Frame(fenetre, padding="3 3 12 12") cadre.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S)) # le cadre s'étire si l'on étire la fenêtre fenetre.columnconfigure(0, weight=1) fenetre.rowconfigure(0, weight=1) # Création des zones de saisie z1_entry = ttk.Entry(cadre, width=7, textvariable=IUz1) m1_entry = ttk.Entry(cadre, width=7, textvariable=IUm1) z2_entry = ttk.Entry(cadre, width=7, textvariable=IUz2) m2_entry = ttk.Entry(cadre, width=7, textvariable=IUm2) # Création des étiquettes statiques z1_label = ttk.Label(cadre, text="z1") m1_label = ttk.Label(cadre, text="m1") z2_label = ttk.Label(cadre, text="z2") m2_label = ttk.Label(cadre, text="m2") rapport_statique = ttk.Label(cadre, text="Rapport de transmission : ") # Création de l'étiquette dynamique rapport_dynamique = ttk.Label(cadre, textvariable=IUrapport) # Création du bouton bouton = ttk.Button(cadre, text="Calcul", command=calcule) # Placement des éléments (widgets) z1_label.grid(column=1, row=1, sticky=tk.W) z1_entry.grid(column=2, row=1, sticky=(tk.W, tk.E)) m1_label.grid(column=1, row=2, sticky=tk.W) m1_entry.grid(column=2, row=2, sticky=(tk.W, tk.E)) z2_label.grid(column=1, row=3, sticky=tk.W) z2_entry.grid(column=2, row=3, sticky=(tk.W, tk.E)) m2_label.grid(column=1, row=4, sticky=tk.W) m2_entry.grid(column=2, row=4, sticky=(tk.W, tk.E)) rapport_statique.grid(column=1, row=5, sticky=tk.W) rapport_dynamique.grid(column=2, row=5, sticky=(tk.W, tk.E)) bouton.grid(column=2, row=6, sticky=tk.W) # ajoute une gouttière entre les éléments for enfant in cadre.winfo_children(): enfant.grid_configure(padx=5, pady=5) # Emplacement initial du curseur z1_entry.focus() # effet de la touche [entrée] fenetre.bind("<Return>", calcule) # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* configureFenetre() # Affichage et activation de la fenêtre fenetre.mainloop() </syntaxhighlight> {{boîte déroulante fin}} {{voir |{{lien web |url=https://docs.python.org/3/library/tkinter.ttk.html |titre=tkinter.ttk — Tk themed widgets |site=docs.python.org |consulté le=2026-06-11}} }} {{voir |{{lien web |url=https://matplotlib.org/stable/gallery/user_interfaces/embedding_in_tk_sgskip.html |titre=How to embed Matplotlib charts in Tkinter GUI? |site=Matplotlib.org |date=2025-07-15 |consulté le=2026-06-11}} }} === Avec PyQt === Le module PyQt (prononcer \ˈpaɪ.kjut\) permet d'utiliser la bibliothèque Qt dévelopée par Riverbank Computing. Il permet notamment de créer des interfaces graphiques. La communication entre objets Qt se fait par une mécanismes de « signal/emplacement » ''({{lang|en|signal/slot}})''. Un emplacement ''({{lang|en|slot}})'' est une fonction ''({{lang|en|callable}})'' ; un signal est un attribut d'un objet. Si l'attribut signal est défini pour l'emplacement, alors on dit que l'emplacement est relié à un signal. Par exemple, un objet <code>QPushButton</code> dispose du signal <code>clicked</code> qui est émis lorsque l'on clique dessus ; on peut ainsi faire exécuter un emplacement (fonction appelable) <code>action()</code> lorsque l'on clique sur le bouton par le biais du signal <code>clicked</code> : <syntaxhighlight lang="python"> from PyQt5.QtWidgets import QPushButton bouton = QPushButton("Appuies-moi dessus") button.clicked.connect(action()) </syntaxhighlight> {{voir|{{lien web |url=https://www.riverbankcomputing.com/static/Docs/PyQt6/ |titre=Reference guide PyQt6 |site=Riverbank Computing|consulté le=2026-0604}} }} {{...}} == Annotations == Une annotation est un commentaire qui sert à expliciter un type de variable. La syntaxe est différente des commentaires « classiques » : cela permet d'avoir un affichage différent avec les éditeurs de texte ayant une coloration syntaxique, et ces informations peuvent être récupérées par des logiciels extérieurs pour effectuer une documentation automatique ou bien des vérifications de type. Cependant : * comme les commentaires normaux, ils n'ont aucune influence lors de l'exécution du texte ; en particulier : * rien n'oblige à annoter les variables ; * il est possible d'avoir une variable ayant un type différent de son annotation ; le fait de pouvoir définir et changer le type de variable à la volée est une fonctionnalité fondamentale de Python. La syntaxe pour une annotation est : : nom_de_variable + deux-points + espace + type par exemple : <syntaxhighlight lang="python"> a: int </syntaxhighlight> Notez qu'ici, la variable n'est ''pas'' créée. Pour la créer, il faut lui affecter une valeur. Il est possible de l'affecter après ou bien sur la même ligne avec la syntaxe : : nom_de_variable + deux-points + espace + type + espace + égal + espace + valeur par exemple : <syntaxhighlight lang="python"> a: int a = 5 # est équivalent à a: int = 5 </syntaxhighlight> Même si l'annotation n'a pas d'impact sur l'exécution, le type doit être un type existant sinon cela génère une erreur de syntaxe. Les types classiques sont : : <code>int</code> — <code>float</code> — <code>str</code> — <code>bool</code> — <code>list</code> — <code>tuple</code> — <code>dict</code> Il est également possible de mettre une chaîne de caractères : <syntaxhighlight lang="python"> a: "ce que je veux" = 3.1516 </syntaxhighlight> On peut annoter une fonction. Il est possible d'annoter les variables déclarées au sein de la fonction, mais pas les variables globales (puisqu'elle ne sont pas définie au sein de la fonction). On peut aussi annoter : * les variables passées en paramètre, avec la même syntaxe dans les parenthèses ; * annoter le type de la variable de sortie (retournée) en la faisant précéder de <code>-&gt;</code> : <syntaxhighlight lang="python"> def plusCinq(a: float = 0) -> float: return a + 5 </syntaxhighlight> ; Ressources * {{lien web | url = https://www.python.org/dev/peps/pep-0526/ | titre = PEP 526 -- Syntax for Variable Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} * {{lien web | url = https://www.python.org/dev/peps/pep-3107/ | titre = PEP 3107 -- Function Annotations | site = Python.org | consulté le = 2019-04-05 | lang = en }} == Décorateur == Un décorateur est une fonction qui s'applique à une fonction, à la manière de la composition mathématique ''g'' ∘ ƒ = ''g''(ƒ). Mais cette composition affecte la fonction elle-même ; l'utilisateur appelle la fonction ƒ mais c'est la fonction ''g'' ∘ ƒ qui s'exécute. Cette fonction ''g'' est appelée le décorateur. L'intérêt est de pouvoir modifier une fonction sans modifier le code de la fonction elle-même. Pour appliquer une décoration, il faut : # Déclarer le décorateur : une fonction qui s'applique à une autre fonction. # Affecter le décorateur à la fonction visée : en mettant <code>@''décoration''</code> juste avant la définition de la fonction. Par exemple : <syntaxhighlight lang="python"> def decorateur(f): print("Avant la fonction") f() print("après la fonction") @decorateur def afficheFoo(): print("Foo.") afficheFoo # Avant la fonction # Foo. # Après la fonction </syntaxhighlight> Lorsque l'on appelle <code>afficheFoo</code>, on appelle en fait <code>decorateur(afficheFoo)</code>. Si la fonction à modifier admet des paramètres, il faut définir une fonction enveloppante dans le décorateur. Par exemple, nous définissons ci-dessous un décorateur <code>deuxFois()</code> qui fait s'exécuter deux fois de suite la fonction : <syntaxhighlight lang="python"> def deuxFois(f): def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # conteneurFonction </syntaxhighlight> Nous voyons que l'application du décorateur a modifié le nom de la fonction — pas le nom de la variable qui contient la fonction mais bien son nom « intime ». Pour éviter cela, on utilise la méthode <code>wraps()</code> du module <code>functools</code> : <syntaxhighlight lang="python"> import functools def deuxFois(f): @functools.wraps(f) def conteneurFonction(*args, **kwargs): f(*args, **kwargs) f(*args, **kwargs) return conteneurFonction @deuxFois def plusCinq(a: int = 0): print(a + 5) plusCinq(2) # 7 # 7 print(plusCinq.__name__) # plusCinq </syntaxhighlight> On peut par exemple utiliser un décorateur pour la mémoïsation. La mémoïsation est une méthode consistant à mémoriser les valeurs d'une fonction au fur et à mesure de son utilisation ; ainsi, si l'on veut évaluer la fonction avec les mêmes entrées, on se contente d'aller chercher la valeur enregistrée ce qui est plus rapide. On sacrifie donc la place mémoire au profit de la rapidité. On peut trouver des décorateurs de mémoïsation aux adresses suivantes : * https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize * https://gist.github.com/robcowie/1357800 ; Ressources : {{lien web | url = https://www.python.org/dev/peps/pep-0318/ | titre = PEP 318 -- Decorators for Functions and Methods | site = Python.org | lang = en | consulté le = 2019-04-05 }} == Manipulation de fichiers == === Importer le contenu d'un fichier === Python possède la fonction <code lang="python">open()</code> qui permet d'ouvrir un fichier. Ouvrir signifie qu'il crée un objet de type <code>file</code> qui possède notamment les méthodes <code lang="python">.read()</code> et <code lang="python">.write()</code>. Il peut s'agir d'un objet de type « fichier binaire » ''({{lang|en|binary file}})'' ou « fichier texte » ''({{lang|en|text file}})''. Si par exemple on veut utiliser (et donc lire) le contenu du fichier texte <code>monfichier.txt</code>, on écrit : <syntaxhighlight lang="python"> fichier = open("monfichier.txt", "rt") … fichier.close() </syntaxhighlight> Le paramètre <code>"rt"</code> signifie que nous ouvrons le fichier en lecture ''({{lang|en|read}})'' et qu'il s'agit d'un objet de type fichier texte. Notons deux choses : * en faisant cela, nous ne faisons qu'associer le fichier à un objet Python, nous n'avons pas encore importé les données ; * si nous ouvrons le fichier, il faut le fermer par la suite ; c'est pourquoi nous utilisons la méthode <code lang="python">.close()</code>. Pour éviter d'avoir à fermer le fichier, nous pouvons l'ouvrir au sein d'un contexte : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: … </syntaxhighlight> Notons aussi que la chaîne de caractères indiquant le nom du fichier peut contenir le chemin d'accès au répertoire (dossier), mais sous Microsoft Windows, il faut utiliser des barres de fractions <code>/</code> pour séparer les sous-répertoires au lieu de la barre inversée habituelle, par exemple : <syntaxhighlight lang="python"> chemin = "C:/Temp/monfichier.txt" with open(chemin, "rt") as fichier: … </syntaxhighlight> Pour mettre les données du fichier dans la variable <code>contenu</code>, nous écrivons donc : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() print(contenu) </syntaxhighlight> et si nous ne voulons lire que les <code>n</code> premiers caractères (<code>n</code> étant un entier), nous utilisons <code lang="python">contenu = fichier.read(n)</code>. Cette lecture est séquentielle, c'est-à-dire que si nous appliquons la méthode plusieurs fois, nous reprenons la lecture là où nous l'avons laissée. Si nous voulons lire une ligne, nous utilisons la méthode <code lang="python">.readline()</code>. La lecture ligne par ligne est également séquentielle. Nous pouvons aussi créer une liste dont chaque élément est une ligne du fichier ; nous utilisons alors la méthode <code lang="python">.readlines()</code> (notez le pluriel). Chaque élément de la liste se termine par le caractère de fin de ligne <code lang="python">\n</code>. Pour l'enlever, nous pouvons utiliser la méthode <code lang="python">.rstrip()</code> pour chaque élément de la liste, par exemple. L'exemple complet est alors : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.readlines() contenu = [item.rstrip() for item in contenu] print(contenu) </syntaxhighlight> === Exporter du contenu vers un fichier === Si nous voulons créer un fichier texte <code>monfichier.txt</code> pour y mettre le contenu de la variable <code>texte</code>, alors nous utilisons : <syntaxhighlight lang="python"> with open("monfichier.txt", "wt") as fichier: fichier.write(texte) </syntaxhighlight> Le module principal important pour la manipulation de fichiers est est <code lang="python">os</code>. === Exploiter le contenu d'un fichier texte === Avec un fichier texte, la méthode <code lang="python">.read()</code> crée une variable de type texte. Nous pouvons séparer cette variable en différentes lignes avec la méthode <code lang="python">.splitlines()</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une ligne. Si maintenant une ligne contient plusieurs données séparées par un séparateur commun, par exemple un espace, nous pouvons séparer les données par la méthode <code lang="python">.split(''séparateur'')</code>. Cela crée une liste de chaînes de caractères, chaque chaîne étant une donnée. Si par exemple le fichier est du type CSV ''({{lang|en|comma separated values}}'', valeurs séparées par une virgule), l'exploitation du fichier est : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(",") for item in contenu] </syntaxhighlight> La variable <code>contenu</code> est une liste de listes. Pour avoir la ''n''<sup>e</sup> valeurs de la ''m''<sup>e</sup> ligne, on utilise : <syntaxhighlight lang="python"> contenu[m-1][n-1] </syntaxhighlight> Si l'on veut extraire la ligne ''m'' il suffit d'écrire : <syntaxhighlight lang="python"> contenu[m-1] </syntaxhighlight> mais si l'on veut la colonne ''n'', le plus simple est d'utiliser une définition en compréhension : <syntaxhighlight lang="python"> [ligne[n-1] for ligne in contenu] </syntaxhighlight> Dans certains fichiers CSV, les séparateurs de valeurs ne sont pas des virgules, on peut donc utiliser un autre caractère pour le séparateur. Concernant les séparateurs particuliers : * si le séparateur est une tabulation, on utilise <code lang="python">\t</code> : <code lang="python">contenu = [item.split("\t") for item in contenu]</code> ; * si le séparateur est un nombre arbitraire d'espaces et/ou de tabulation, on ne définit aucun séparateur : <code lang="python">contenu = [item.split() for item in contenu]</code>. Si la première ligne contient les en-têtes des colonnes, on peut l'enlever avec la fonction <code lang="python">del()</code> : <syntaxhighlight lang="python"> with open("monfichier.txt", "rt") as fichier: contenu = fichier.read() contenu = contenu.splitlines() del(contenu[0]) contenu = [item.split(",") for item in contenu] </syntaxhighlight> Certains logiciels créent des fichiers en utilisant le séparateur décimal régional, qui en France est la virgule. Pour remplacer les virgules par des points, on peut utiliser la méthode <code lang="python">.replace()</code>, de préférence ''avant'' de séparer les valeurs : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.replace(",", ".") for item in contenu] # remplace les virgules par des points contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule </syntaxhighlight> en effet, lorsque l'on a séparé les valeurs, on a une liste de liste, il faut alors balayer les sous-listes ce qui prend plus de temps : <syntaxhighlight lang="python"> contenu = contenu.splitlines() contenu = [item.split(";") for item in contenu] # si le séparateur est un point-virgule contenu = [[subitem.replace(",", ".") for subitem in item] for item in contenu] # remplace les virgules par des points </syntaxhighlight> '''Exemple complet''' Supposons que l'on ait un fichier texte de la forme : <syntaxhighlight lang="text"> x y z V 0.0 1.5 3.2 8.657 0.4 1.5 3.2 8.392 0.2 1.5 3.2 8.485 ... </syntaxhighlight> C'est un fichier valeurs V associées à des points de coordonnées ''(x, y, z)'' (un champ V sur l'espace, donc). Nous remarquons que seule la coordonnée ''x'' change : les données concernent la droite (''y'' = 1,5 ; ''z'' = 3,2). Nous remarquons aussi que les valeurs de ''x'' ne sont pas classées par ordre croissant ni décroissant. Nous voulons au final avoir une matrice [[''x''], [V]] triée par ''x'' croissant. Pour cela, nous pouvons faire : <syntaxhighlight lang="python"> with open(nomdefichier, "rt") ad fichier: contenu = fichier.read() contenu = contenu.splitlines() contenu = [item.split(" ") for item in contenu contenu = contenu[1:] # élimine la première ligne x = np.array([float(ligne[0]) for ligne in contenu]) V = np.array([float(ligne[3]) for ligne in contenu]) donnees = np.concatenate((x.reshape(-1, 1), V.reshape(-1, 1)), axis=1) # matrice [[x], [V]] ind = np.argsort(donnees[:, 0]) donnees = donnees[ind, :] # matrice triée plt.plot(donnees[:, 0], donnees[:, 1]) </syntaxhighlight> {{note|Pour le tri, voir [[../Manipulation_de_matrices#Fonctions_et_méthodes_de_base|''Manipulation de matrices'' &gt; ''Fonctions et méthodes de base'']].}} === Cas d'un fichier CSV === Si le fichier CSV ne contient que des valeurs numériques, on peut utiliser : <syntaxhighlight lang="python"> valeurs = np.loadtxt(chemin+nomfic, delimiter=",") # si le séparateur est une virgule </syntaxhighlight> Il existe un module <code lang="python">csv</code> dédié aux fichiers CSV. La manipulation du fichier se fait comme suit : <syntaxhighlight lang="python"> import csv with open(chemin+nomfic, "rt") as fichier: lecteur = csv.reader(fichier, delimiter=",") contenu = [ligne for ligne in lecteur] print(contenu) </syntaxhighlight> === Utilisation de Pandas === Pandas<ref>https://pandas.pydata.org/</ref> est un module gérant les tableaux de données, appelés <em lang="en">data frames</em>. Voici quelques commandes utiles : <syntaxhighlight lang="python"> import numpy as np import pandas as pd M = np.random.rand(10, 10) # crée une matrice NumPy aléatoire de dimension 10 × 10 tableau = pd.DataFrame(M) # transforme la matrice en tableau DataFrame tableau.to_csv("tableau.csv") # enregistre le tableau dans un fichier CSV donnees = pd.read_csv("tableau.csv").to_numpy() # lit le fichier et transforme le tableau DataFrame en matrice NumPy </syntaxhighlight> Par défaut, la fonction <code>pd.read_csv()</code> considère que le séparateur est une virgule, et la commande <code>pd.read_table()</code> que c'est une tabulation. On peut définir le séparateur avec le paramètre <code>sep</code> : <syntaxhighlight lang="python"> donnees = pd.read_csv("tableau.csv", sep=";") </syntaxhighlight> On peut utiliser les séparateurs spéciaux : * <code>\t</code> : tabulation ; * <code>\s+</code> : nombre arbitraire d'espaces. On peut par ailleurs utiliser les paramètres suivants : * <code>dialect</code> : syntaxe du fichier, par exemple <code>dialect = "excel"</code> ; * <code>nrows</code> (entier) : nombre de lignes lues ; * <code>skiprows</code> (entier) : nombre de lignes sautées (non lues) en début de fichier ; * <code>header</code> (entier) : numéro de ligne utilisé pour l'en-tête, par exemple <code>header = 0</code> pour la première ligne ; * <code>skip_blank_lines</code> (booléen) : si la valeur est vraie (<code>True</code>), ne lit pas les lignes vide ; sinon, met une valeur <code>nan</code>. Par exemple : <syntaxhighlight lang="python"> donnees1 = pd.read_csv("tableau.csv", nrows=1, sep="\s+").to_numpy() donnees2 = pd.read_csv("tableau.csv", skiprows=3, sep="\s+").to_numpy() </syntaxhighlight> {{voir|{{lien web |url=https://pandas.pydata.org/docs/user_guide/io.html |titre=IO tools (text, CSV, HDF5, …) |site=Pandas |consulté le=2026-05-06}} }} == Exporter un programme Python == Vous pouvez créer un fichier « Python pur » <code>.py</code>. Pour cela, dans le menu <code>fichier/file</code> de Jupyter, choisir <code>télécharger/download</code> au format <code>.py</code> ; le fichier se trouve alors dans le répertoire de téléchargement du navigateur. == Recommandations == Les recommandations de programmation sont générales et ne sont en grande partie pas spécifiques à Python. {{voir|[[Découvrir_Scilab/Programmation#Recommandations]]}} == Ressources == * {{lien web | url = https://www.python.org/dev/peps/pep-0008/ | titre = PEP 8 -- Style Guide for Python Code | site = Python documentation | consulté le = 2019-03-14 }} == Notes et références == {{références}} ---- [[../Fonctions mathématiques générales|Fonctions mathématiques générales]] &lt; [[../|↑]] &gt; [[../Graphiques|Graphiques]] {{DEFAULTSORT:Elements de programmation}} [[Catégorie:Python pour le calcul scientifique (livre)]] sa1ym8km4pwgtwbwup3b6ppfxd1lurm Python pour le calcul scientifique/Manipulation de matrices 0 72889 768481 762143 2026-06-24T11:56:40Z Cdang 1202 /* Fonctions et méthodes de base */ voc. 768481 wikitext text/x-wiki Les matrices sont un élément primordial du calcul scientifique sur ordinateur pour deux raisons : # L'algèbre linéaire est au cœur de nombreux calculs. # Les matrices sont l'élément de base du calcul vectorisé qui permet un gain de temps appréciable. Pour pouvoir expliter les matrices, il faut charger le module NumPy ; nous utilisons également Matplotlib pour les graphiques. Ainsi, les programmes contiennent tous au début : <syntaxhighlight lang="python"> #!/usr/bin/python3 import numpy as np import matplotlib.pyplot as plt </syntaxhighlight> == Rappels et complément sur le tranchage == Soit une liste L composée de ''n'' éléments. * Les éléments sont numérotés de 0 à ''n'' – 1. * Le premier élément s'obtient par <code lang="python">L[0]</code>. * Le i-ème élément s'obtient par <code lang="python">L[''i'' - 1]</code>. * L'avant-dernier élément s'obtient par <code lang="python">L[-2]</code>. * Le dernier élément s'obtient par <code lang="python">L[-1]</code>. * La sous-liste composée des éléments contigus ''i'' à ''j'' s'obtient par <code lang="python">L[''i'' - 1:j]</code>. Ainsi, <code lang="python">L[0:1]</code> va extraire le premier élément, <code lang="python">L[1:-1]</code> va extraire tous les éléments sauf le premier et le dernier. NumPy fournit des fonctions permettant de manipuler les matrices : * <code lang="python">np.append(A, B)</code> : fusionne les vecteurs A et B ;<br /> s'il s'agit de matrices ou de tenseurs, la fonction les « aplatit », les transforme en vecteur ;<br />si l'on veut intégrer B dans A, on utilise <code lang="python">A = np.append(A, B)</code> ; * <code lang="python">np.append(A, B, axis = ''i'')</code> : fusionne les tenseurs selon l'indice ''i'' (<code>0</code> pour le premier indice, <code>1</code> pour le deuxième…) ; * <code lang="python">np.insert(A, i, m)</code> : insère le vecteur ''m'' dans le vecteur A (ou la matrice A aplatie) à l'emplacement ''i'' ; * <code lang="python">np.insert(A, i, M, axis = ''j'')</code> : insère le tenseur M dans le tenseur A à l'emplacement ''i'' de l'indice ''j'' ; * <code lang="python">np.delete(A, I)</code> : efface les éléments définis par le tranchage I du vecteur A (ou de la matrice A aplatie) ; * <code lang="python">np.delete(A, I, axis = ''j'')</code> : efface les éléments définis par le tranchage I selon l'indice ''j'' du tenseur A. == Définir un tenseur == Un tenseur est similaire à une liste mais il est défini par la fonction <code>np.array()</code>. La définition et l'extraction de composante utilise la méthode du découpage en tranches ''({{lang|en|slicing}})''. '''Exemples''' <syntaxhighlight lang="python"> a = np.array([1, 3, 5, 7]) # vecteur bc = np.array([[1], [2], [3], [4]]) # matrice 4 × 1 (matrice colonne) bl = np.array([[1, 2, 3, 4]]) # matrice 1 × 4 (matrice ligne) c = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) # matrice 3 × 3 d = np.array([[[1, 2, 3], [2, 3, 4]], [[10, 9, 8], [ 7, 6, 5]]]) # tenseur d'ordre 3, de dimension 3 × 2 × 2 </syntaxhighlight> Notez que dans NumPy, un vecteur n'est pas la même chose qu'une matrice ligne ou colonne. Un vecteur de dimension ''n'' est un tenseur d'ordre 1 et de dimension ''n'' ; une matrice ligne ou colonne est un tenseur d'ordre 2 et de dimension 1 × ''n'' ou ''n'' × 1. <syntaxhighlight lang="python"> a = np.array([1, 2, 3]) b = np.array([[1, 2, 3]]) c = np.array([[1], [2], [3]]) print(a.size, b.size, c.size) # 3 3 3 print(a.ndim, b.ndim, c.ndim) # 1 2 2 print(a.shape, b.shape, c.shape) # (3,) (1, 3) (3, 1) </syntaxhighlight> La fonction <code>np.arange()</code> est similaire à la fonction <code>range()</code> pour les liste ; elle génère un vecteur de réels. La fonction <code>np.linspace()</code> permet également de créer un vecteur de même type, mais on indique le dernier nombre alors que la règle du découpage en tranches fait que le nombre maximal indiqué à <code>np.arange()</code> est le premier nombre qui ne ''figure pas'' dans le vecteur.). La fonction <code>np.zeros()</code> génère une matrice nulle, <code>np.zeros_like()</code> une matrice nulle ayant les dimensions d'une matrice fournie comme modèle. De même, <code>np.ones()</code> et <code>np.ones_like()</code> crée des matrices, dont toutes les composantes sont à 1. La fonction <code>np.eye()</code> crée une matrice unité. '''Exemples''' <syntaxhighlight lang="python"> e = np.arange(0, 2, 0.1) # vecteur [0, 0.1, 0.2…, 1.8, 1.9] f = np.linspace(0, 2, 5) # 5 nombres entre 0 et 2 soit le vecteur [0, 0.5, 1, 1.5, 2] g = np.zeros(3) # vecteur nul de dimension 3 h = np.zeros((3, 3)) # matrice nulle 3 × 3 k = np.ones_like(a) # matrice de 1 de même dimension que a u = np.eye(3) # matrice unité 3 × 3 </syntaxhighlight> Le paramètre <code>dtype</code> permet de forcer le type. Par exemple <syntaxhighlight lang="python"> a = np.array([1, 2, 3], dtype="complex") k = np.ones_like(a, dtype="int") </syntaxhighlight> La commande <code>np.linspace()</code> peut créer des matrices colonne : on donne la première et la dernière ligne ; par exemple : : <syntaxhighlight lang="python"> np.linspace([1, -1], [10, -10], 4) # [[ 1. -1.] # [ 4. -4.] # [ 7. -7.] # [ 10. -10.]] </syntaxhighlight> Les commandes <code>np.geomspace()</code> et <code>np.geomspace()</code> fonctionnent comme <code>np.linspace()</code>, mais avec une progression logarithmique. La commande <code>np.geomspace(a, b, n)</code> crée un vecteur (ou une matrice colonne) allant de ''a'' à ''b'' alors que <code>np.logspace(a, b, n)</code> crée un vecteur (ou une matrice colonne) allant de 10<sup>''a''</sup> à 10<sup>''b''</sup>. La méthode <code>.reshape()</code> remet en forme une matrice. Par exemple, pour transformer un vecteur de dimension 9 en une matrice 3 × 3 : <syntaxhighlight lang="python"> a = np.arange(1, 10) b = a.reshape(3, 3) # ou bien directement c = np.arange(1, 10).reshape(3, 3) </syntaxhighlight> Avec la méthode <code>.reshape()</code>, on peut utiliser la valeur –1 pour une des dimensions ; sa valeur est alors automatiquement calculée en fonction du nombre d'éléments et de l'autre dimension. On peut aussi utiliser une dimension vide ; cela crée alors un vecteur. Par exemple, pour une matrice M quelconque : <syntaxhighlight lang="python"> M.reshape(-1, 1) # crée une matrice colonne M.reshape(1, -1) # crée une matrice ligne M.reshape(-1,) # crée un vecteur </syntaxhighlight> La méthode <code>.fill()</code> remplit la matrice avec un scalaire : <syntaxhighlight lang="python"> b.fill(5) # remplace les valeurs de b par la valeur 5 </syntaxhighlight> == Extraction matricielle == Si l'on veut extraire les colonnes 1 et 3 pour toutes les lignes d'une matrice M, on utilise : <syntaxhighlight lang="python"> M[:, [0, 2]] </syntaxhighlight> == Assemblage de matrices == Si l'on veut regrouper deux matrices, on utilise la commande <code>np.concatenate()</code>. On utilise le paramètre ''axis'' pour indiquer si l'on empile les matrices l'une au-dessus de l'autre (<code>axis=0</code>) ou bien l'une derrière l'autre (<code>axis=1</code>). Par exemple : <syntaxhighlight lang="python"> A = np.matrix([[1 ,2], [3, 4]]) B = np.matrix([[5 ,6], [7, 8]]) np.concatenate((A, B), axis = 0) # [[1 2] # [3 4] # [5 6] # [7 8]] np.concatenate((A, B), axis = 1) # [[1 2 5 6] # [3 4 7 8]] </syntaxhighlight> Si l'on veut transformer deux vecteurs en une matrice de deux colonnes, chaque vecteur occupant une colonne : <syntaxhighlight lang="python"> A = np.matrix([1 ,2]) B = np.matrix([3 ,4]) np.concatenate((A.reshape(-1, 1), B.reshape(-1, 1)), axis = 1) # [[1 3] # [2 4]] </syntaxhighlight> == Opérations matricielles == Les quatre opérations classiques <code lang="python>+</code>, <code lang="python>-</code> et <code lang="python>/</code> ne fonctionnent qu'entre tenseurs de mêmes dimensions et sont des opérations élément par élément ''({{lang|en|elementwise operations}})'' : * <code lang="python">(A + B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] + B[i, j, k]</code> ; * <code lang="python">(A - B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] - B[i, j, k]</code> ; * <code lang="python">(A / B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] / B[i, j, k]</code>. La multiplication élément par élément se fait avec : <code lang="python">np.multiply(A, B)</code> qui vaut <code lang="python">A[i, j, k] * B[i, j, k]</code>. De même, les fonctions <code lang="python>np.add()</code>, <code lang="python>np.subtract()</code>, <code lang="python>np.multiply()</code> et <code lang="python>np.divide()</code> effectuent des opérations élément par élément sur des tenseurs de mêmes dimensions : * <code lang="python">np.add(A, B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] + B[i, j, k]</code> ; * <code lang="python">np.subtract(A, B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] - B[i, j, k]</code> ; * <code lang="python">np.multiply(A, B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] * B[i, j, k]</code> ; * <code lang="python">np.divide(A, B)[i, j, k]</code> vaut <code lang="python">A[i, j, k] / B[i, j, k]</code>. La multiplication matricielle, au sens de l'algèbre linéaire, se fait avec les fonctions <code lang="python">np.dot()</code> ou <code lang="python">np.matmul()</code>, ou bien avec l'opérateur <code>@</code>. <syntaxhighlight lang="python"> a = np.matrix([[1, 2], [3, 4]]) b = np.matrix([[5, 6], [7, 8]]) print(a @ b) # np.matmul(a, b) # [[19 22] # [43 50]] </syntaxhighlight> Pour un poduit scalaire : <syntaxhighlight lang="python"> A = np.matrix([1, 2, 3]) B = np.matrix([4, 5, 6]) print(np.dot(A, B.T)) # [[</nowiki>32]] print(np.dot(A, B.T)[0, 0]) # 32 </syntaxhighlight> Notez que : * pour le produit par un scalaire, les fonctions <code lang="python">np.multiply()</code> et l'opérateur <code lang="python">*</code> sont plus performants ; * la fonction <code lang="python">np.dot()</code> est plus performante pour le produit scalaire de deux vecteurs réels ; * lorsque l'on a des vecteurs complexes, la fonction <code lang="python">np.vdot()</code> fait le produit par le conjugué du premier membre (<code lang="python">np.vdot(a, b) == np.dot(a.conj(), b)</code>) ; * la fonction <code lang="python">np.matmul()</code> et l'opérateur <code lang="python">@</code> (<code lang="python">A @ B</code>) sont plus performants pour un produit matriciel. L'opérateur <code>@=</code> fait un produit matriciel en modifiant la variable elle-même (à l'image de <code>*=</code> pour les nombres). == Calcul vectorisé == Les fonctions de NumPy traitent en général les matrices en entier. Ainsi, il n'est pas nécessaire de créer une boucle pour faire défiler les indices un par un. Il en résulte un code clair et compact et surtout un plus grande rapidité d'exécution. Par exemple : <syntaxhighlight lang="python"> x = np.linspace(0, 2*np.pi, 50) # 50 points entre 0 et 2π y = np.sin(x) plt.plot(x, y) </syntaxhighlight> La variable <code>x</code> est un vecteur de 50 valeurs et il est traité en une seule passe par la fonction sinus <code>np.sin()</code>. Outre le tranchage ''({{lang|en|slicing}})'', on peut utiliser deux autres méthodes pour extraire certaines valeurs d'une matrice : * utiliser un vecteur ou une matrice d'indices, Python extrait alors les valeurs correspondant aux indices ; * utiliser un vecteur ou une matrice de booléens de même dimension que a matrice ; Python extrait alors les valeurs correspondant aux <code>True</code>, la matrice booléenne est un « masque » pour la matrice d'origine. Par exemple : <syntaxhighlight lang="python"> a = np.arange(0, 10) b = np.array([1, 3, 5, 7, 9]) c = np.array([True, True, False, False, True, False, True, False, False, True]) print(a[b], "\n", a[c]) </syntaxhighlight> Si l'on veut inverser tous les éléments d'une matrice de bolléens, il faut utiliser la fonction <code>np.logical_not()</code> '''Exercice''' Écrire un programme Python mettant en œuvre le [[w:crible d'Érathostène|crible d'Érathostène]] pour trouver les nombres premiers inférieurs à une valeur donnée. {{boîte déroulante début|Solution}} <syntaxhighlight lang="python"> #!/usr/bin/env python # coding: utf-8 import numpy as np import matplotlib.pyplot as plt # *************** # *************** # ** Fonctions ** # *************** # *************** def eratosthene(limite): # Détermine la liste des nombres premiers entre 1 et N # par le crible d'Ératosthène # Entrées : limite : nombre entier, N # Sorties : liste : vecteur d'entiers,liste des nombres premiers indices = (np.ones(limite) == 1) # vecteur de booléens tous à True # à la fin, indice(i-1) est True si i est premier, False sinon indices[0]=False # 1 n'est pas premier imax = int(limite) i = 2 # initialisation repete = (i <= imax) while repete: if indices[i-1]: jmax = int(limite/i) j = np.arange(1, jmax)+1 indices[i*j-1]=False # élimination des multiples de i test = (i*jmax == imax) i = i + 1 repete = i*i < limite # condition d'arrêt liste0 = np.arange(limite) liste = liste0[indices]+1 return liste # ************************* # ************************* # ** Programme principal ** # ************************* # ************************* print("***** Recherche de nombres premiers par le crible d'Ératosthène *****\n") nmax = eval(input("Entrez la valeur maximale : ")) resultat = eratosthene(nmax) print("\n", resultat.shape[0], "nombres premiers entre 1 et", nmax, ":\n") print(resultat) plt.plot(resultat, np.zeros_like(resultat), "|") </syntaxhighlight> L'extraction par un vecteur d'indice intervient dans l'instruction : <syntaxhighlight lang="python"> indices[i*j-1]=False </syntaxhighlight> qui élimine en une seule passe tous les multiples de ''i''. L'extraction par un vecteur booléen intervient dans l'instruction : <syntaxhighlight lang="python"> liste = liste0[indices]+1 </syntaxhighlight> qui permet d'extraire toutes la valeurs conservées en une seule passe. {{boîte déroulante fin}} == Attributs == La classe <code>ndarray</code>, qui définit les matrices, possède un certain nombre d'attributs : * <code>.shape</code> : dimensions de la matrice ; * <code>.ndim</code> : ordre du tenseur ; * <code>.size</code> : nombre d'éléments ; * <code>.dtype</code> : type des éléments. <syntaxhighlight lang="python"> a = np.linspace(1, 9, 9) print("a", a, "\n", " ; shape :", a.shape, " ; dim : ", a.ndim, " ; size : ", a.size, " ; dtype : ", a.dtype, "\n") </syntaxhighlight> * <code>.real</code>, <code>.imag</code> : parties réelle et imaginaire de la matrice ; * <code>.flat</code> : liste des éléments de la matrice ; les éléments sont réorganisés en une liste ; * <code>.T</code> : transposée. <syntaxhighlight lang="python">a = np.arange(0, 9).reshape(3, 3) print(a) # [[0 1 2] # [3 4 5] # [6 7 8]] print(a.T) # [[0 3 6] # [1 4 7] # [2 5 8]] print(a.flat[:]) # array([0, 1, 2, 3, 4, 5, 6, 7, 8]) </syntaxhighlight> ; Ressources : Section « Attribute », {{lien web | url = https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html | titre = numpy.ndarray | site = Numpy and Scipy Documentation | consulté le = 2019-03-16 }} == Fonctions et méthodes de base == La classe <code>ndarray</code> possède un certain nombre de méthodes : * <code>.min()</code> et <code>.max()</code> : valeurs respectivement minimale et maximale ; * <code>.ptp()</code> : amplitude « max – min » ''({{lang|en|peak to peak}})'' ; * <code>.argmin()</code> et <code>argmax()</code> : indice où se trouvent les valeurs respectivement minimale et maximale ; * <code>.sum()</code>, <code>prod()</code> : somme et produit de tous les éléments de la matrice ; * <code>.cumsum()</code>, <code>cumprod()</code> : somme et produit cumulés. <syntaxhighlight lang="python"> a = np.linspace(1, 9, 9) print("min : ", a.min(), "; max : ", a.max(), "\n", "sum : ", a.sum(), "; cumsum : ", a.cumsum(), "\n", "prod : ", a.prod(), "; cumprod : ", a.cumprod(), "\n") </syntaxhighlight> Méthodes statistiques : * <code>.mean()</code> : moyenne ; * <code>.std()</code> : écart type ''({{lang|en|standard deviation}})''. {{loupe|../Statistiques}} Extraction de données : * <code>.diagonal()</code> : vecteur contenant les éléments de la diagonale ; * <code>.flatten()</code> : matrice « aplatie », c'est-à-dire vecteur contenant les éléments réorganisés en liste ; par rapport à l'attribut <code>.flat</code>, on peut choisir le sens de linéarisation (par lignes, <code>.flatten(C)</code>, ou par colonnes, <code>.flatten(F)</code>) mais cela crée une copie, on ne peut pas par exemple s'en servir pour modifier la matrice ; * <code>.tofile()</code> : crée un fichier texte contenant les valeurs de la matrice ; par exemple, pour une matrice <code>a</code> et pour séparer les valeurs par un point-virgule : <syntaxhighlight lang="python"> a.tofile("matriceA.txt", sep=" ; ") </syntaxhighlight> * <code>.astype(''type'')</code> : copie la matrice en convertissant le type de données : <syntaxhighlight lang="python"> a = a.astype(float) # pour avoir une matrice de réels en virgule flottante a = a.astype(str) # pour avoir une matrice de chaînes de caractères </syntaxhighlight> Tri : * <code>np.sort(M, i)</code> : crée une copie et trie la matrice selon l'axe ''i'' (0 pour le premier indice, 1 pour le deuxième… la valeur par défaut est –1 pour le dernier indice, la valeur ''none'' aplatit la matrice) ; <code>np.sort(M, 0)</code> trie chaque colonne indépendamment par ordre croissant, <code>np.sort(M, 1)</code> trie chaque ligne indépendamment par ordre croissant ; * <code>M.sort(i)</code> : cette méthode trie la matrice en elle-même ; * <code>np.argsort(M, i)</code> : crée une matrice contenant le nouvel indice, selon l'axe ''i'', de chaque élément. <syntaxhighlight lang="python"> M = np.array([[1, 5, 7, 5], [2, 9, 4, 3], [9, 1, 7, 5]]) M.sort(1) # tri des lignes indépendamment -> [[1, 5, 5, 7], [2, 3, 4, 9], [1, 5, 7, 9]] </syntaxhighlight> Pour trier les lignes selon la deuxième colonne d'une matrice, tout en conservant les lignes intactes, on peut faire comme suit : <syntaxhighlight lang="python"> M = np.array([[1, 5, 7, 5], [2, 9, 4, 3], [9, 1, 7, 5]]) ind = np.argsort(M[:, 1]) # indices de tri selon la 2e colonne N = M[ind, :] # réarrangement des lignes -> [[9, *1*, 7, 5], [1, *5*, 7, 5], [2, *9*, 4, 3]] </syntaxhighlight> Pour faire un tri lexicographique, on utilise la fonction <code>np.lexsort()</code> en indiquant les différentes colonnes : <syntaxhighlight lang="python"> M = np.array([[1, 5, 7, 5], [2, 9, 4, 3], [9, 1, 7, 5], [2, 9, 8, 5]]) ind = np.lexsort((M[:, 3], M[:, 2], M[:, 1], M[:, 0])) # indices de tri selon la 1re, puis la 2e, puis la 3e, puis la 4e colonne N = M[ind, :] # réarrangement des lignes -> [[1, 5, 7, 5], [2, 9, 4, 3], [2, 9, 8, 5], [9, 1, 7, 5]] </syntaxhighlight> Le tri se fait par ordre croissant. Pour trier par ordre décroissant, on inverse l'ordre de la matrice en faisant une extraction avec un pas de moins un, par exemple pour inverser les lignes : <syntaxhighlight lang="python"> M = M[:, ::-1] </syntaxhighlight> Algèbre linéaire : * <code>a.dot(b)</code> : produit matriciel ''a''⋅''b'' ; on peut aussi écrire <code>a@b</code> ; * <code>.trace()</code> : trace de la matrice (somme des éléments diagonaux) ; * <code>.transpose()</code> : transpose la matrice, résultat similaire à l'attribut <code>.T</code> ; * <code>np.cross()</code> : produit vectoriel dans ℝ³. {{loupe|../Algèbre linéaire}} Matrices de booléens : * <code>.all()</code> : applique un « et » logique à toutes les valeurs de la matrice ; * <code>.any()</code> : applique un « ou » logique à toutes les valeurs de la matrice. {{loupe|../Fonctions mathématiques générales#Fonctions booléennes}} Autre méthodes : * <code>.conj()</code> : conjugué des valeurs complexes ; * <code>.nonzero()</code> : n-uplet contenant les indices des valeurs non-nulles ; * <code>.round(n)</code> : arrondit les valeurs à la ''n''-ième décimale. ; Ressources : Section « Method », {{lien web | url = https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html | titre = numpy.ndarray | site = Numpy and Scipy Documentation | consulté le = 2019-03-16 }} == Propagation == Le terme « propagation » ''({{lang|en|broadcasting}})'' désigne la manière dont Python complète les matrice lorsque des dimensions manquent. Supposons que l'on veuille additionner deux matrices M<sub>1</sub> et M<sub>2</sub> de dimensions ''m''<sub>1</sub> × ''n''<sub>1</sub> et ''m''<sub>2</sub> × ''n''<sub>2</sub> différentes. Alors : * le résultat a pour dimension max(''m''<sub>1</sub>, ''m''<sub>2</sub>) × max(''n''<sub>1</sub>, ''n''<sub>2</sub>) ; * si une des dimensions vaut 1, alors les valeurs de l'autre dimension sont dupliquées ; * sinon, les dimensions manquantes pour chaque matrice sont complétées par des 1. Par exemple : : <math>\mathrm{A} = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} </math> : <math>5 + \mathrm{A} = \begin{pmatrix} 5 & 5 \\ 5 & 5 \end{pmatrix} + \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} </math> :: La matrice (5) est de dimension 1 × 1, la valeur « 5 » est donc répétée dans les deux dimensions <syntaxhighlight lang="python"> A = np.array([[1, 2], [3, 4]]) print(5 + A) # [[6 7] # [7 8]] </syntaxhighlight> : <math>(5, 4) + \mathrm{A} = \begin{pmatrix} 5 & 4 \\ 5 & 4 \end{pmatrix} + \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} </math> <syntaxhighlight lang="python"> print(np.array([[5, 4]]) + A) # [[6 6] # [6 8]] </syntaxhighlight> : <math>\begin{pmatrix} 5 \\ 4 \end{pmatrix} + \mathrm{A} = \begin{pmatrix} 5 & 5 \\ 4 & 4 \end{pmatrix} + \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} </math> <syntaxhighlight lang="python"> print(np.array([[5], [4]]) + A) # [[6 7] # [7 8]] </syntaxhighlight> == Fonctions « universelles » == Les fonctions universelles ''({{lang|en|ufunc}})'' sont les fonctions s'appliquant aux matrices, des fonctions vectorisées. ; Ressource : {{lien web | url = https://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs | titre = Available ufuncs | site = SciPy documentation | consulté le = 2019-03-21 }} == Algèbre linéaire == {{loupe|../Algèbre linéaire}} == Notes et références == {{références}} ---- [[../Graphiques|Graphiques]] &lt; [[../|↑]] &gt; [[../Polynômes|Polynômes]] [[Catégorie:Python pour le calcul scientifique (livre)]] h696x0n6x2qidc38cleykvzdcefglm3 Dictionnaire de philosophie/Esthétique dans la pensée chinoise 0 83023 768459 766853 2026-06-24T03:16:44Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768459 wikitext text/x-wiki {{DicoPhilo|Esthétique dans la pensée chinoise|lecture=oui}} L'esthétique dans la pensée chinoise représente un domaine complexe et profondément enraciné dans les traditions philosophiques du Confucianisme, du Taoïsme et du Bouddhisme. Contrairement à la tradition occidentale qui a développé l'esthétique comme discipline autonome à partir du XVIIIe siècle, la pensée chinoise intègre la réflexion sur le beau au sein d'une vision cosmologique et éthique globale.<ref>Qi, Zhixiang (2024). ''The Spirit of Traditional Chinese Aesthetics'', Shanghai Peoples Publishing House / Springer Nature Singapore, p. 1-7.</ref> == Origines et fondements conceptuels == Avant d'entrer dans le détail des notions, une précaution s'impose. Parler d'« esthétique chinoise » au sens d'une discipline constituée ne va pas de soi. Dans la Chine ancienne et médiévale, il n'existe pas de domaine du savoir équivalent à l{{'}}''Ästhetik'' fondée par Alexander Baumgarten au XVIIIe siècle, ni de terme indigène qui en couvrirait exactement l'extension. Le mot ''meixue'' (美學, « étude du beau »), forgé pour traduire l'« esthétique » occidentale, est emprunté par les lettrés chinois au japonais ''bigaku'' à la charnière des XIXe et XXe siècles. Il se diffuse en Chine à travers les travaux de Wang Guowei (1877-1927) et de Cai Yuanpei (1868-1940), qui appellent à une « éducation par le beau » (''meiyu'', 美育) et permettent l'émergence rapide d'un nouveau champ de recherche.<ref>Cai, Zong-qi (éd.) (2004). ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawaii Press, p. 21-22.</ref><ref>Cheng, Anne (1997). ''Histoire de la pensée chinoise'', Paris, Seuil, p. 651-654.</ref> Ce que l'on désigne aujourd'hui comme « esthétique chinoise traditionnelle » correspond donc à une reconstruction rétrospective. Elle rassemble un ensemble de problèmes, de catégories d'appréciation et de pratiques (poésie, calligraphie, peinture de paysage, musique rituelle, art des jardins, critique littéraire) disséminés dans les classiques confucéens, les textes taoïstes, les sūtras bouddhiques, les traités poétiques et picturaux. Ces matériaux ne forment pas un système unifié, mais une constellation de discussions où les questions d'apparence, de forme, de saveur et d'agrément se trouvent étroitement liées à des questions rituelles, morales, cosmologiques, politiques et sociales. Comme le souligne Cai Zong-qi, la tradition chinoise ne dispose pas d'un terme indigène équivalant exactement à « beauté » : le mot ''mei'' n'a jamais servi à intégrer dans un tout cohérent les diverses branches de l'art, et aucun traité ancien n'a pour objet ''mei'' comme tel.<ref>Cai, Zong-qi (éd.) (2004). ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawaii Press, p. 20-22.</ref> Haun Saussy montre quant à lui que la cohérence supposée d'une « esthétique chinoise » résulte largement d'un travail comparatiste tardif plutôt que d'une discipline indigène.<ref>Saussy, Haun (1993). ''The Problem of a Chinese Aesthetic'', Stanford, Stanford University Press, p. 13-46.</ref> L'exposé qui suit emprunte une grille de lecture proposée par Qi Zhixiang dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), qui distingue cinq formes esthétiques : la saveur (味, ''wei''), le motif culturel (文, ''wen''), le cœur-esprit (心, ''xin''), la Voie (道, ''dao'') et l'adéquation à la nature (適性, ''shixing''). Cette typologie présente une valeur pédagogique mais reste une lecture interprétative parmi d'autres : la sinologie contemporaine (Anne Cheng, François Jullien, Yolaine Escande, Stephen Owen, Haun Saussy, Ronald Egan, Susan Bush, James J. Y. Liu, Pauline Yu, Curie Virág) propose d'autres organisations possibles du champ, qui privilégient tour à tour les enjeux cosmologiques, rhétoriques, politiques, religieux ou affectifs.<ref>Jullien, François (1991). ''Éloge de la fadeur. À partir de la pensée et de l'esthétique de la Chine'', Arles, Philippe Picquier.</ref><ref>Escande, Yolaine (2005). ''Montagnes et eaux. La culture du shanshui'', Paris, Hermann.</ref><ref>Owen, Stephen (1992). ''Readings in Chinese Literary Thought'', Cambridge (Mass.), Harvard University Press.</ref><ref>Egan, Ronald (2006). ''The Problem of Beauty: Aesthetic Thought and Pursuits in Northern Song Dynasty China'', Cambridge (Mass.), Harvard University Asia Center.</ref><ref>Virág, Curie (2017). ''The Emotions in Early Chinese Philosophy'', Oxford, Oxford University Press.</ref> Enfin, les rapprochements et contrastes établis dans ce qui suit entre traditions chinoises et traditions européennes valent comme balises pédagogiques, et non comme oppositions de civilisation. La pensée européenne a connu, elle aussi, des esthétiques du goût, du plaisir, de la sensibilité corporelle et de la formation morale ; et la pensée chinoise ne se réduit pas à l'unité du beau et du moral. Les schémas qui en accentuent l'opposition gardent une fonction heuristique à condition d'en mesurer la part de simplification. === La notion de ''mei'' (美) === ==== L'étymologie et la composition graphique du caractère ==== Dans la tradition chinoise ancienne, le concept central pour comprendre l'esthétique est celui de ''mei'' (美), qui désigne à la fois le beau, ce qui est agréable, et la bonté. L'étude étymologique et graphologique du caractère ''mei'' révèle des dimensions fondamentales de la conception chinoise de la beauté, enracinée dans l'expérience sensible et le plaisir.<ref>Qi, Zhixiang (2024). ''The Spirit of Traditional Chinese Aesthetics'', Shanghai Peoples Publishing House / Springer Nature Singapore, p. 1-7.</ref><ref>Liu, James J. Y. (1987). ''Chinese Literary Theories'', Sichuan Renmin Press, p. 144.</ref> Selon le ''Shuowen Jiezi'' (說文解字, « Explication des caractères simples et analyse des caractères composés »), le premier dictionnaire étymologique chinois composé par Xu Shen (vers 58-148 de notre ère) et présenté à l'empereur An des Han en 121 de notre ère, le caractère ''mei'' signifie originellement « délicieux » ou « savoureux ».<ref>Xu Shen (121 CE). ''Shuowen Jiezi'', édition Yuelu Academy Press, 2006, cité dans Qi, Zhixiang (2024), p. 1, 11.</ref><ref>Legge, James (1861). ''The Chinese Classics'', vol. 1-5, Oxford University Press.</ref> L'entrée de Xu Shen, « La beauté est ce qui est délicieux » (甘也), établit dès l'origine un lien étroit entre l'esthétique et la satisfaction sensorielle, particulièrement gustative.<ref>Xu Shen, cité dans Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 1.</ref><ref>Gao, J. (2018). « The Original Meaning of the Chinese Character for "Beauty" », ''PhilPapers''.</ref> La composition graphique du caractère ''mei'' renforce cette dimension sensible, selon l'interprétation traditionnelle qu'en donne le ''Shuowen Jiezi''. Une mise en garde s'impose ici : la graphie ancienne d'un caractère éclaire un imaginaire culturel, mais elle ne livre pas à elle seule l'origine philosophique d'un concept. L'analyse qui suit relève donc d'une reconstruction sémantique, défendue par la tradition philologique chinoise, et reprise par les esthétiques modernes. Dans les écritures anciennes (écriture sur os oraculaires et écriture sigillaire), ''mei'' (美) est constitué de deux éléments : ''yang'' (羊, « mouton » ou « brebis ») et ''da'' (大, « grand »). Xu Shen explique : « Le caractère se compose des radicaux pour mouton (羊) et grand (大). Parmi les six sortes d'animaux domestiques, le mouton est une source majeure de viande ».<ref>Xu Shen, ''Shuowen Jiezi'', cité dans Qi, Zhixiang (2024), p. 11.</ref><ref>Li, Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawaii Press, p. 1.</ref> Cette étymologie suggère l'image d'un gros mouton, symbole d'abondance alimentaire et de satisfaction des besoins vitaux dans la Chine ancienne.<ref>Zang Kehe (1990). ''Chinese Characters and Aesthetic Mentality'' (Hanzi Wenxue He Shenmei Xinli), Xuelin Press, p. 13, cité dans Qi, Zhixiang (2024), p. 11.</ref> Le philologue Zang Kehe note que l'explication « le mouton comme source principale de viande » apparaît probablement pour la première fois dans l'édition annotée du ''Shuowen Jiezi'' par Xu Xuan (916-991) de la dynastie Song.<ref>Zang Kehe (1990). ''Chinese Characters and Aesthetic Mentality'', Xuelin Press, p. 13, cité dans Qi, Zhixiang (2024), p. 11.</ref><ref>Xu Xuan (916-991). ''Annotations on Shuowen Jiezi'' (édition annotée).</ref> Le commentateur Wang Yun (1784-1854) de la dynastie Qing précise : « Un mouton gras est agréable au goût. La nourriture est généralement appelée ''xiu'' (羞), et l'agneau est le plat principal... ainsi le mot prend le radical du mouton plutôt que celui du bœuf ».<ref>Wang Yun (vers 1830). ''Explicating Shuowen Jiezi'' (說文句讀), vol. 7, cité dans Qi, Zhixiang (2024), p. 11.</ref> Cette lecture traditionnelle n'est pas la seule possible. Le philosophe Li Zehou propose une hypothèse étymologique alternative, fondée sur les inscriptions oraculaires et sur les bronzes anciens. L'élément inférieur du caractère ''mei'', en apparence « grand » (大, ''da''), représenterait à l'origine un homme debout vu de face, possiblement un prêtre ou un chef accomplissant un rôle totémique. Le caractère ''mei'' désignerait alors « un grand homme portant une coiffe de bélier, ou orné de motifs de bélier, lorsqu'il accomplit des rituels chamaniques où les cornes ou la tête de l'animal expriment son pouvoir mystique et son autorité ».<ref>Li, Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawaii Press, p. 1-2.</ref> Le caractère pour « danse » (舞, ''wu'') et celui pour « chaman » (巫, ''wu'') sont d'ailleurs interchangeables dans les écritures oraculaires les plus anciennes, et les fouilles archéologiques attestent l'importance du chant et de la danse rituels dans la Chine pré-Zhou.<ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 4-5.</ref> Li Zehou reconnaît le caractère spéculatif de cette hypothèse, mais souligne qu'elle permet d'articuler les deux versants du Shuowen : « lorsqu'un bélier est grand, il est beau » (beauté comme sensible) et « beauté et bonté sont synonymes » (beauté comme totémique et morale). Ces deux versants se rejoindraient ainsi dans la culture chamanique des origines, où la satisfaction des sens et la valeur communautaire des rites se trouvaient unies.<ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 2-4.</ref> ==== La dimension psychologique : beauté et plaisir ==== Cette interprétation étymologique a souvent été comprise comme suggérant un lien ancien entre la beauté, le plaisir sensible et la valeur communautaire des rites. Plusieurs courants de la pensée chinoise abordent en effet le beau moins comme une qualité purement formelle ou contemplative que comme une expérience de plaisir (悅, ''yue'') et de satisfaction qui engage les sens tout en gardant une portée spirituelle et morale.<ref>Qi, Zhixiang (2024), p. 1-3.</ref><ref>Li Zehou (1985). « Tentative Comments on the Chinese Wisdom », dans ''On the History of Chinese Philosophy'', Anhui Literature and Art Press, 1999, p. 299-326.</ref> Wang Bi (226-249), philosophe néo-taoïste de l'école des Mystères (玄學, ''Xuanxue''), établit clairement cette dimension psychologique dans ses ''Annotations au Daodejing de Laozi'' : « La beauté suscite l'appréciation, tout comme la laideur provoque le dégoût » (美者人之所欣,惡者人之所憎).<ref>Wang Bi, ''Annotations au Daodejing de Laozi'' (老子道德經注), édité par Lou Yulie, dans ''Les annotations de Wang Bi expliquées'' (王弼集校釋), vol. 1, Zhonghua Book Company, 1980, p. 6, cité dans Qi, Zhixiang (2024), p. 1-2.</ref><ref>Wagner, R. G. (1986). « Wang Bi: The Structure of the Laozi's Pointers », ''Journal of the American Oriental Society'', vol. 106, no 4, p. 663-672.</ref> Cette définition souligne que la beauté est déterminée par les réactions affectives du sujet : elle est ce qui procure une sensation heureuse et agréable, tandis que la laideur (惡, ''wu'') est ce qui provoque aversion et déplaisir.<ref>Qi, Zhixiang (2024), p. 2.</ref> Le philosophe Wang Chong (27-97 de notre ère), dans son ''Lunheng'' (論衡, « Discussions pesées »), développe cette idée en distinguant différentes catégories de plaisirs sensoriels : « La délicatesse (美味, ''meiwei'') est ce qu'un gourmet aimerait savourer. Les visions belles (美色, ''meise'') sont différentes les unes des autres, mais elles sont toutes agréables aux yeux ».<ref>Wang Chong, ''Lunheng'' (vers 80 CE), cité dans Qi, Zhixiang (2024), p. 2.</ref><ref>Forke, Alfred (1962). ''Lun-heng: Philosophical Essays of Wang Ch'ung'', New York: Paragon Book Gallery.</ref> De même, Ge Hong (283-343) affirme : « Les gammes pentatoniques varient, mais la musique plaît aux oreilles ».<ref>Ge Hong, ''Baopuzi'' (抱朴子, « Le Maître qui embrasse la simplicité »), section ''Boyu'' (博喻), cité dans Qi, Zhixiang (2024), p. 2.</ref> ==== La relation entre ''mei'' et ''shan'' : beauté et bonté ==== Le lien étroit entre beauté et bonté constitue une autre dimension essentielle du concept de ''mei''. Dans le ''Shuowen Jiezi'', Xu Shen note : « La beauté (美) est la bonté (善) » (美與善同意).<ref>Xu Shen, ''Shuowen Jiezi'', cité dans Qi, Zhixiang (2024), p. 3.</ref><ref>Fu, X. (2021). « Is the Unity of Goodness and Beauty the Distinctive Feature of Chinese Aesthetics? », ''Asian and African Studies'', vol. 30, no 1, p. 82-107.</ref> Ce rapprochement est plus fortement souligné par la tradition confucéenne et les arts lettrés qui en relèvent. Il oriente une part importante de la critique poétique, picturale et calligraphique chinoise, sans qu'il faille pour autant l'attribuer uniformément à toutes les écoles : le taoïsme y opposera ses propres réserves, et le bouddhisme distinguera les apparences belles de la libération spirituelle. Le caractère ''shan'' (善, « bon », « vertueux ») partage également une origine liée à la nourriture. Dans les inscriptions sur bronze, notamment sur le vase Shanfu Ke Ding (善父克鼎), le caractère ''shan'' est utilisé comme ''shan'' (膳), signifiant « nourriture » ou « repas ».<ref>Qi, Zhixiang (2024), p. 12, note sur les inscriptions sur bronze.</ref><ref>Shanghai Museum Collection, « Shanfu Ke Ding » (vase rituel), accessible sur https://www.shanghaimuseum.net.</ref> Dans les ''Rites de Zhou'' (周禮, ''Zhouli''), texte confucéen classique, les deux caractères sont utilisés de manière interchangeable : le chef (善夫, ''shanfu'') est celui qui gère les affaires de nourriture (善羞, ''shanxiu'') pour le roi, et la nourriture préparée est appelée « bonne nourriture » (善食, ''shanshi'') ou « belle nourriture » (美食, ''meishi'').<ref>''Rites de Zhou'', chapitre « Offices du Ciel » (天官), cité dans Qi, Zhixiang (2024), p. 12.</ref> Le commentateur Zheng Xuan (127-200) de la dynastie Han de l'Est note : « ''Shan'' (善) se prononce de la même manière que ''shan'' (膳), et les belles choses sont également appelées ''zhenshan'' (珍膳, "mets délicieux") ».<ref>Zheng Xuan, commentaire cité dans le ''Jiyun'' (集韻, « Rimes collectées »), dictionnaire de 1037, cité dans Qi, Zhixiang (2024), p. 12.</ref><ref>Zheng Xuan. ''Commentary on the Rites of Zhou'' (Zhouli Zhushu), vols. 2-3.</ref> ==== La valeur et la dimension spirituelle de la beauté ==== Zhixiang Qi, dans son ouvrage de synthèse ''The Spirit of Traditional Chinese Aesthetics'' (2024), définit la beauté chinoise comme « l'objet précieux du sentiment de délice » (''the valuable sense of delight and its aesthetic objects'').<ref>Qi, Zhixiang (2024), p. 1, 4.</ref><ref>Lao Chengwan (2010). ''On Ancient Chinese Aesthetic Forms'' (中國古代美學形態論), Chinese Social Science Press.</ref> Cette formulation souligne deux dimensions essentielles : Premièrement, la beauté englobe à la fois le sentiment subjectif de délice (le ''meigan'' 美感, « sens de la beauté ») et les objets qui suscitent ce sentiment (le ''mei'' 美, « beauté » au sens objectif). En pratique esthétique, on distingue ainsi la sensation agréable ressentie et les objets qui l'éveillent.<ref>Qi, Zhixiang (2024), p. 4.</ref> Deuxièmement, la valeur (''valuable'') associée à cette délice provient de la fonction utilitaire des objets esthétiques pour l'existence du sujet. Cependant, cette utilité n'est pas seulement matérielle ou sensuelle. Bien que les êtres humains recherchent naturellement le plaisir et évitent la souffrance, leur quête peut s'opposer à leurs valeurs spirituelles s'ils s'adonnent à un plaisir sensuel excessif, transformant ainsi la beauté en laideur.<ref>Qi, Zhixiang (2024), p. 2.</ref><ref>Wang, Keping (2021). « A Sketch of Chinese Aesthetics », dans Ghilardi, Marcello et Ram-Prasad, Chakravarthi (éds.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, p. 21-45.</ref> Zhuangzi (vers 369-286 avant notre ère), philosophe taoïste, exprime cette idée paradoxale : « Le bonheur parfait dérive de l'absence de jouissance excessive » (至樂無樂).<ref>Zhuangzi, cité dans Qi, Zhixiang (2024), p. 2.</ref> Il critique les plaisirs sensoriels excessifs : « Il y a cinq cas dans lesquels la nature innée est perdue. Premièrement, les cinq couleurs confondent les yeux et les rendent moins perçants. Deuxièmement, les cinq sons musicaux confondent les oreilles et les rendent moins aigus. Troisièmement, les cinq odeurs remplissent le nez et le bloquent. Quatrièmement, les cinq saveurs gâtent la bouche et la rendent moins sensible. Cinquièmement, les goûts et les dégoûts perturbent l'esprit et troublent la nature innée. Ces cinq cas sont tous des exemples où la nature innée est endommagée ».<ref>Zhuangzi, traduction anglaise citée dans Qi, Zhixiang (2024), p. 3.</ref><ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 78-93, sur la critique zhuangzienne des plaisirs sensoriels excessifs.</ref> Zuo Qiuming (vers 556-452 avant notre ère), historien contemporain de Confucius, insiste sur cette même idée : « Quand la musique devient stridente ou la beauté visuelle aveuglante, leur beauté est perdue ».<ref>Zuo Qiuming, ''Guoyu'' (國語, « Discours des États »), cité dans Qi, Zhixiang (2024), p. 3.</ref> Le ''Maître Lü's Spring and Autumn Annals'' (呂氏春秋, ''Lüshi Chunqiu'') met en garde : « Bien que nos oreilles aient soif de sons, nos yeux de couleurs, nos nez de senteurs, nos langues de saveurs, nous devons nous arrêter quand cela s'avère contraire à l'éthique pour nos vies. Par conséquent, les sages choisissent seulement de profiter des plaisirs sensuels qui sont bons pour la nature, et s'abstiennent de ce qui est mauvais pour la nature, et c'est ainsi que l'on protège notre nature innée ».<ref>''Lüshi Chunqiu'', sections ''Guisheng'' (貴生) et ''Bensheng'' (本生), cité dans Qi, Zhixiang (2024), p. 3.</ref> ==== La fusion de l'esthétique et de l'éthique ==== Pour une part importante des philosophes chinois anciens, c'est le plaisir spirituel et éthique, au-delà de la jouissance sensuelle ou matérielle, qui définit le bonheur ultime associé à la beauté.<ref>Qi, Zhixiang (2024), p. 2.</ref><ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 10-31, sur la tradition des rites et de la musique.</ref> Cette orientation, particulièrement marquée dans la tradition confucéenne, se retrouve, sous des accents différents et parfois contradictoires, dans plusieurs écoles : Le néo-confucéen Zhu Xi (1130-1200) commente que, selon Confucius, « la bonté est l'essence de la beauté » (善者美之質).<ref>Zhu Xi, ''Sishu Zhangju Jizhu'' (四書章句集注, « Annotations rassemblées sur les Quatre Livres »), cité dans Qi, Zhixiang (2024), p. 3.</ref><ref>Thompson, K. (2015). « Zhu Xi », ''Stanford Encyclopedia of Philosophy''.</ref> Mencius (372-289 avant notre ère) affirme : « L'accomplissement moral est la beauté elle-même » (充實之謂美).<ref>Mencius, ''Mengzi'', cité dans Qi, Zhixiang (2024), p. 3.</ref><ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 58-77, sur la beauté morale chez Mencius.</ref> Xunzi (vers 310-235 avant notre ère) ajoute : « Si [la moralité d'un gentleman confucéen] est imparfaite ou impure, elle ne mérite pas le nom de beauté ».<ref>Xunzi, ''Quanxue'' (勸學, « Exhortation à l'étude »), cité dans Qi, Zhixiang (2024), p. 3.</ref> Le ''Shangshu'' (尚書, ''Classique de l'histoire''), l'un des plus anciens classiques confucéens, répudie « l'indulgence dans le plaisir et l'abandon de l'aspiration », tout en invitant chacun à « constamment améliorer sa moralité pour bien se reposer ».<ref>''Shangshu'', cité dans Qi, Zhixiang (2024), p. 3-4.</ref> Le ''Yijing'' (易經, ''Livre des Mutations'') affirme : « La beauté est une affaire de l'esprit/cœur » (心, ''xin'').<ref>''Yijing'', cité dans Qi, Zhixiang (2024), p. 4.</ref><ref>Hon, T. F. (2019). « Chinese Philosophy of Change (Yijing) », ''Stanford Encyclopedia of Philosophy''.</ref> Ces enseignements sont perpétués par les générations ultérieures. Wang Chong écrit : « La bonté et la beauté sont agréables ».<ref>Wang Chong, ''Lunheng'', cité dans Qi, Zhixiang (2024), p. 4.</ref><ref>Pokora, T. (1975). « Wang Chong's Epistemology of Testimony », ''Philosophy East and West'', vol. 25, no 3.</ref> Cette tradition se poursuit jusqu'au philosophe contemporain Li Zehou (1930-2021), qui dans ''The Chinese Aesthetic Tradition'' (1989) commence son enquête par une analyse étymologique du terme ''mei'', montrant que sa signification est « étymologiquement liée au goût délicieux et aux danseurs totémiques ».<ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 1-4.</ref><ref>Wilkinson, R. (2011). « The Chinese Aesthetic Tradition – Li Zehou », ''The Philosophical Quarterly'', vol. 61, no 244, p. 668-670.</ref> ==== L'extension métaphorique : de la saveur à tous les sens ==== Un trait remarquable de plusieurs traditions chinoises, et qui les différencie d'une partie de la tradition philosophique européenne issue de Platon, d'Aristote et de Thomas d'Aquin, est que la saveur (''wei'', 味) y est considérée comme synonyme de beauté (''mei''), et que le vocabulaire gustatif s'y emploie métaphoriquement pour décrire les sensations perçues par d'autres sens, ainsi que les satisfactions intellectuelles et spirituelles. La pensée européenne n'a pas pour autant ignoré ces registres : les philosophies du goût et de la gastronomie, des moralistes du XVIIe siècle à Brillat-Savarin, en sont la preuve. La différence porte plutôt sur la place faite à la saveur dans la définition même du beau.<ref>Qi, Zhixiang (2024), p. 10-18.</ref><ref>Collingwood, R. G. (1987). ''The Principles of Art'', trad. Wang Zhiyuan et Chen Huazhong, Chinese Social Science Press, p. 40.</ref> Alors que dans la tradition esthétique occidentale, depuis les Grecs, la beauté est principalement associée à la vue et à l'ouïe, comme l'affirme Socrate dans le ''Grand Hippias'' : « le beau est ce qui plaît par l'ouïe et la vue »<ref>Platon, ''Grand Hippias'', cité dans Qi, Zhixiang (2024), p. 10.</ref>, l'esthétique chinoise inclut pleinement le sens du goût. Saint Thomas d'Aquin (1225-1274) réitère cette exclusion : « Les sens les plus intimes sont la vision et l'audition. Nous ne louons que les paysages ou les sons comme beaux, mais n'utilisons jamais le même mot pour les objets d'autres perceptions sensorielles comme le goût et l'odorat ».<ref>Thomas d'Aquin, cité dans Qi, Zhixiang (2024), p. 10.</ref> Dans la langue chinoise, le terme ''mei'' est fréquemment utilisé dans la culture gastronomique, comme en témoignent les expressions : ''meishi'' (美食, « belle/délicieuse nourriture »), ''meijiu'' (美酒, « beau/délicieux vin »), ''xianmei'' (鮮美, « umami et délectable »), ''feimei'' (肥美, « riche et savoureux »), ''ganmei'' (甘美, « doux/succulent »), et ''tianmei'' (甜美, « doux/moelleux »).<ref>Qi, Zhixiang (2024), p. 18.</ref> Plus largement, ''wei'' et ''mei'' ne sont pas limités à décrire les objets de la gustation, mais s'étendent aux autres sens (visuels, olfactifs et auditifs) ainsi qu'aux satisfactions intellectuelles et spirituelles.<ref>Qi, Zhixiang (2024), p. 18.</ref><ref>Prince Zhaoming (501-531). ''Qiqi Essays on Food'' (齊齊食論), cité dans ''The Complete Work in the Liang Dynasty'' (Quan Liang Wen), vol. 20, Zhonghua Book Company, 1958.</ref> ==== Synthèse : la conception chinoise de la beauté ==== À partir des enseignements chinois anciens sur le concept de beauté, Zhixiang Qi conclut que la beauté est l'objet précieux du sentiment de délice (''beauty is the valuable sense of delight and its aesthetic objects'').<ref>Qi, Zhixiang (2024), p. 4.</ref> Cette définition englobe plusieurs dimensions : * Les objets qui éveillent des sentiments sensuels agréables constituent la beauté formelle (formes, couleurs, sons, saveurs). * Les objets qui, par un traitement cognitif, génèrent des sentiments heureux constituent la beauté intérieure (morale, spirituelle, intellectuelle). * La beauté inclut tous les objets précieux qui inspirent des délices aux yeux et à l'esprit.<ref>Qi, Zhixiang (2024), p. 4.</ref> Cette conception, enracinée dans le plaisir sensible tout en s'élevant vers le plaisir spirituel et moral, marque une inflexion sensible par rapport aux esthétiques occidentales modernes qui, depuis Kant, ont cherché à isoler le jugement de goût de l'utilité et de la moralité. Le philosophe Li Zehou propose, dans cette ligne, de caractériser la culture chinoise traditionnelle comme une « culture du plaisir » (''culture of pleasure''), valorisant la vie humaine terrestre, par contraste avec une « culture du péché » (''culture of sin'') qu'il associe au christianisme occidental.<ref>Li Zehou (1985). « Tentative Comments on the Chinese Wisdom » (試論中國人的智慧), dans ''On the History of Chinese Philosophy'' (中國思想史論), Anhui Literature and Art Press, 1999, p. 299-326, cité dans Qi, Zhixiang (2024), p. 9.</ref><ref>Rosker, J. (2023). « Li Zehou's Ideas on Chinese Modernity Revisited », ''Asian Studies'', vol. 11, no 2, p. 15-41.</ref> L'historien Lao Chengwan identifie de même les formes esthétiques chinoises anciennes comme « l'étude du bonheur » (''the study of happiness'').<ref>Lao Chengwan (2010). ''On Ancient Chinese Aesthetic Forms'' (中國古代美學形態論), Chinese Social Science Press, cité dans Qi, Zhixiang (2024), p. 10.</ref> Ce schéma garde une valeur pédagogique, mais relève d'une lecture interprétative plus que d'une description neutre : les traditions européennes ont également connu des esthétiques du plaisir, d'Épicure à Hume, de Montaigne aux philosophies du goût du XVIIIe siècle, et le christianisme ne se réduit nullement à une « culture du péché ».<ref>Cheng, Anne (1997). ''Histoire de la pensée chinoise'', Paris, Seuil, p. 32-65, 196-202, sur les difficultés des oppositions trop tranchées entre « Chine » et « Occident ».</ref> Ainsi, la notion de ''mei'' ouvre l'accès aux fondements sensibles, affectifs, éthiques et spirituels d'une part importante des traditions esthétiques chinoises, où la beauté est traitée moins comme une abstraction métaphysique que comme une expérience vivante, ancrée dans le monde sensible et orientée vers la perfection morale. Ces problèmes ne se posent pas dans un espace purement contemplatif. Les pratiques où s'élaborent les jugements de beauté (poésie ''shi'' et ''ci'', calligraphie, peinture de paysage ''shanshui'', musique rituelle, art des jardins, critique littéraire) appartiennent à des milieux sociaux précis : la classe lettrée des fonctionnaires-littérateurs (士大夫, ''shidafu''), les cercles de cour, les communautés monastiques bouddhiques et taoïstes, les écoles d'examens impériaux. Ces pratiques sont liées à des aspirations politiques, à des stratégies de distinction sociale, à des critiques de la cour ou du pouvoir, à des engagements religieux. La discussion des formes y est donc inséparable d'enjeux institutionnels et politiques, sur lesquels la sinologie contemporaine, notamment les travaux de Susan Bush sur les lettrés peintres et de Ronald Egan sur la poétique des Song du Nord, a beaucoup insisté.<ref>Bush, Susan (1971). ''The Chinese Literati on Painting: Su Shih (1037-1101) to Tung Ch'i-ch'ang (1555-1636)'', Cambridge (Mass.), Harvard University Press.</ref><ref>Egan, Ronald (2006). ''The Problem of Beauty: Aesthetic Thought and Pursuits in Northern Song Dynasty China'', op. cit., p. 1-30.</ref> === Les cinq formes esthétiques fondamentales === Qi Zhixiang, dans la synthèse déjà citée, propose de résumer plusieurs lignes de l'esthétique chinoise traditionnelle, comprise comme la quête d'un « objet précieux du sentiment de délice » (''valuable sense of delight''), autour de cinq formes complémentaires : la saveur (味, ''wei''), le motif/culture (文, ''wen''), le cœur/esprit (心, ''xin''), la Voie (道, ''dao''), et l'adéquation à la nature (適性, ''shixing'').<ref>Qi, Zhixiang (2024). ''The Spirit of Traditional Chinese Aesthetics'', Shanghai Peoples Publishing House / Springer Nature Singapore, p. 4-5.</ref> Cette typologie offre une grille de lecture pédagogique : elle agrège des thèmes dispersés dans les classiques, les traités poétiques, picturaux et calligraphiques, et permet de comparer leur traitement par les écoles confucéenne, taoïste et bouddhique. On la conserve ici à ce titre, sans la présenter comme un système strictement attesté dans les sources anciennes : il s'agit d'un outil d'exposition, parmi d'autres possibles dans la sinologie contemporaine. ==== Première forme : la saveur (味, ''wei'') ==== La première forme esthétique concerne la saveur (味, ''wei''). La saveur désigne les goûts qui procurent du réconfort aux personnes. L'appréciation de la saveur constitue la base de la tradition esthétique chinoise qui valorise le plaisir plutôt que l'ascétisme.<ref>Qi, Zhixiang (2024), p. 5.</ref> L'analyse étymologique du caractère ''mei'' (美) a montré que la beauté est originellement associée au goût délicieux. Cette place de la saveur dans le vocabulaire esthétique chinois est remarquable lorsqu'on la compare à la philosophie issue des Grecs, qui a tendu à exclure le sens du goût de la sphère esthétique stricte, Socrate déclarant dans le ''Grand Hippias'' que « le beau est ce qui plaît par l'ouïe et la vue »<ref>Platon, ''Grand Hippias'', cité dans Qi, Zhixiang (2024), p. 10.</ref>, et saint Thomas d'Aquin (1225-1274) réitérant : « Les sens les plus intimes sont la vision et l'audition. Nous ne louons que les paysages ou les sons comme beaux, mais n'utilisons jamais le même mot pour les objets d'autres perceptions sensorielles comme le goût et l'odorat »<ref>Thomas d'Aquin, cité dans Qi, Zhixiang (2024), p. 10.</ref>. Le contraste vaut pour cette ligne philosophique précise, et non pour toute la pensée européenne, qui a aussi connu des théories du goût et du jugement gustatif, des moralistes classiques aux philosophes du XVIIIe siècle. L'esthétique chinoise se distingue surtout par la place centrale qu'elle accorde à la saveur dans la définition même du beau. Le terme ''wei'' désigne originellement tous les types de goûts (aigre, amer, doux, épicé, salé), mais lorsqu'il entre dans le domaine esthétique, il se réfère spécifiquement aux goûts agréables comme la douceur (甘, ''gan'') ou les saveurs plaisantes en général.<ref>Qi, Zhixiang (2024), p. 17.</ref> La langue chinoise utilise fréquemment ''mei'' dans la culture gastronomique : ''meishi'' (美食, « belle/délicieuse nourriture »), ''meijiu'' (美酒, « beau/délicieux vin »), ''xianmei'' (鮮美, « umami et délectable »), ''feimei'' (肥美, « riche et savoureux »), ''ganmei'' (甘美, « doux/succulent »), et ''tianmei'' (甜美, « doux/moelleux »).<ref>Qi, Zhixiang (2024), p. 18.</ref> ''wei'' et ''mei'' ne sont pas limités à décrire les objets de la gustation : ils s'étendent aux autres sens, visuels, olfactifs et auditifs, ainsi qu'aux satisfactions intellectuelles et spirituelles.<ref>Qi, Zhixiang (2024), p. 18.</ref> Le sens (意, ''yi'') est considéré comme une sorte de saveur (''wei''), d'où les concepts de ''yiwei'' (意味, « sens avec saveur ») et ''quwei'' (趣味, « intérêt avec saveur »). Comme le note le ''Qiqi Essays on Food'' (齊齊食論), ouvrage sur la culture gustative du Prince Zhaoming (501-531) : « Les pêches, les jujubes et les taros réjouissent le palais et satisfont l'esprit ; ils sont les plus beaux et les plus agréables ».<ref>Prince Zhaoming, ''Qiqi Essays on Food'', cité dans Qi, Zhixiang (2024), p. 18.</ref> Ici, le plaisir sensuel et la satisfaction spirituelle sont complémentaires. Enfin, la théorie de ''wei mei'' n'indique pas que l'objectif soit d'obtenir une stimulation sensorielle plus forte. Sous l'influence des traditions taoïste et bouddhiste Chan, les philosophes chinois ont développé une appréciation pour la beauté-saveur de la fadeur (淡, ''dan''). De la compréhension par Laozi de la fadeur (無味, ''wu wei'') du Dao à la notion bouddhiste Chan de « saveur dans le fade » (淡中之味, ''dan zhong zhi wei'') valorisée sous la dynastie Song du Sud, l'esthétique de la fadeur devient centrale dans la tradition chinoise.<ref>Qi, Zhixiang (2024), p. 18, 188-199.</ref><ref>Sernelj, T. (2025). « The Beauty of Emptiness—The Foundational Root of Chinese Aesthetics », ''Asian Studies'', vol. 13, no 3, p. 71-93.</ref> ==== Deuxième forme : le motif/culture (文, ''wen'') ==== La deuxième forme esthétique concerne wen (文), qui se réfère aux motifs, aux rituels, à l'écriture, à la littérature, à la culture et à la civilisation. ''Wen'' désigne les formes d'une bonne écriture ou d'une littérature parlée. L'écriture doit être rhétoriquement élégante, et la parole doit être habilement éloquente.<ref>Wang Chong, ''Lunheng'', chapitre 85 « Ziji » (自紀), cité dans Qi, Zhixiang (2024), p. 5.</ref> L'esthétique chinoise traditionnelle valorise la culture et l'ingéniosité littéraire comme moyen de délice. Le caractère ''wen'' (文), dans les écritures sur os oraculaires et les écritures sigillaires, représente des motifs entrecroisés. Comme le note le ''Yijing'' (易經, ''Livre des Mutations'') : « Les anciens appelaient un mélange de choses ''wen'' ».<ref>''Yijing'', cité dans Qi, Zhixiang (2024), p. 19.</ref> Xu Shen explique que « ''wen'', traits entrecroisés, provient de l'imitation des motifs des choses ».<ref>Xu Shen, ''Shuowen Jiezi'', cité dans Qi, Zhixiang (2024), p. 19.</ref> Le sinologue James J. Y. Liu (1926-1986) note avec justesse que ''wen'' était à l'origine un pictogramme se référant aux motifs et aux marques.<ref>James J. Y. Liu, cité dans Qi, Zhixiang (2024), p. 19.</ref> Cai Zong-qi a montré que ''wen'' a connu une expansion sémantique progressive : sous les Zhou, le mot renvoie principalement à l'ordre moral et sociopolitique ; sous les Han, il s'applique de plus en plus à l'ordre des signes graphiques ; à l'époque des Six Dynasties, il en vient à désigner l'ordre dans les paroles, les sons, la musique et les images de la littérature et des arts.<ref>Cai, Zong-qi (éd.) (2004), op. cit., p. 22-23.</ref> Pour cette raison, Cai Zong-qi propose même que ''wen'', plutôt que ''mei'', soit considéré comme le concept indigène le plus proche de ce que la tradition occidentale entend par « beauté », tant sa portée embrasse les dimensions cosmologique, religieuse, sociopolitique, psychologique et artistique.<ref>Cai, Zong-qi (éd.) (2004), op. cit., p. 22.</ref> Dans ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit de la littérature et la Sculpture du dragon''), Liu Xie (465-522) écrit : « L'eau, par nature, est plastique et flexible, permettant la formation d'ondulations ; il est de la nature essentielle des arbres d'être solides, supportant les fleurs sur leurs calices. Le motif ornemental d'une chose est nécessairement conditionné par sa nature essentielle ».<ref>Liu Xie, ''Wenxin Diaolong'', cité dans Qi, Zhixiang (2024), p. 19.</ref><ref>Cai, Zong-qi (ed.) (2001). ''A Chinese Literary Mind: Culture, Creativity and Rhetoric in Wenxin diaolong'', Stanford University Press.</ref> Ici, ''wen'' est utilisé dans son sens originel de motifs. ''Wen'' ne désigne pas seulement des motifs visuels ou des traits. En fait, les complexités des choses peuvent être appelées ''wen''.<ref>Zang Kehe (1990), cité dans Qi, Zhixiang (2024), p. 20.</ref> Prenons la notion de ''sheng wen'' (聲文, « motif sonore ») comme exemple : elle exprime l'idée que la musique est créée par une combinaison de sons. Comme le note le ''Yueji'' (樂記, ''Record of Music'') dans le ''Livre des Rites'' : « Les changements sont produits par la manière dont les sons se répondent les uns aux autres, et ces changements constituent ce que nous appelons les modulations de la voix ».<ref>''Yueji'', cité dans Qi, Zhixiang (2024), p. 20.</ref><ref>Legge, James (trad.). « Record of Music » in ''The Book of Rites'' (Liji), ''Chinese Text Project'', consulté en 2022.</ref> Un autre usage de ''wen'' se trouve dans ''wen shi'' (文飾, « embellissement »), qui définit ''wen'' comme des motifs semblables à du brocart en diverses couleurs, ou des textes significatifs composés de nombreux caractères : « les textes sont comme des motifs ».<ref>Qi, Zhixiang (2024), p. 20.</ref> ''Wen'' peut signifier à la fois motif et texte, et ''wen shi'' se réfère au langage littéraire et à la beauté formelle des compositions. Comme le dit ''Wenxin Diaolong'' : « Pour exprimer adéquatement les idées, les mots doivent être combinés en formes littéraires ; les sentiments sincères doivent être incarnés dans des expressions magistrales ; ce sont les pierres de touche de la composition littéraire ».<ref>Liu Xie, ''Wenxin Diaolong'', cité dans Qi, Zhixiang (2024), p. 20.</ref> Le philologue moderne Zhang Binlin (1869-1936) explique dans ses ''Essais sur le patrimoine culturel national'' (國故論衡, ''Guogu Lunheng'') : « 文 signifie littérature, et les textes, mots et diction sont tous appelés ''wen'' ; pourtant, ce n'est que lorsque c'est coloré et significatif que nous pouvons l'appeler littérature (''wen'') ».<ref>Zhang Binlin, cité dans Qi, Zhixiang (2024), p. 20.</ref> La beauté des formes diversifiées : La lecture grammatologique de ''wen'' révèle la loi de la forme esthétique, les formes diversifiées créent la beauté. Pour que la forme esthétique de ''wen'' soit présente, certaines exigences doivent être satisfaites. Premièrement, il doit y avoir des variations dans les formes. Il n'y aura pas de ''wen'' sans diversité. Le ''Commentaire de Zuo'' (左傳, ''Zuozhuan'') enregistre les propos du ministre Yan Zi au duc Jing de Qi : « La musique est comme la saveur. Une seule saveur ne suffit pas à rendre un plat savoureux ; un seul ton ne peut créer une mélodie... Si un gentleman écoute un zither à corde unique, comment pourrait-il supporter de l'écouter ? ».<ref>''Zuozhuan'', année 20 du règne du duc Zhao, cité dans Qi, Zhixiang (2024), p. 21-22.</ref><ref>Eno, R. (2016). ''Mencius: A Teaching Translation'', Indiana University, p. 112.</ref> La musique, comme les motifs et la société, doit être composée de variétés. Deuxièmement, les variations doivent être organisées. Dans les théories musicales chinoises traditionnelles, la musique doit suivre certaines règles. Le prince Jizha de l'État de Wu, invité à apprécier la musique de la dynastie Zhou dans l'État de Lu, loua les eulogies en disant : « Quand elle est directe, elle n'est pas hautaine ; quand elle est indirecte, elle ne se plie pas. Quand elle est jouée de près, elle n'est pas envahissante ; quand elle est jouée de loin, elle ne se dissipe pas ».<ref>''Zuozhuan'', cité dans Qi, Zhixiang (2024), p. 22.</ref> Ici, l'eulogie exemplifie l'équilibre entre variation et ordre. La variation de ''wen'' : La variation se voit d'abord dans la structure de la composition littéraire, qui est organisée de manière équilibrée : « Les œuvres des anciens, bien que diversifiées, sont structurées par l'équilibre. Si le début est clairsemé, la fin doit être dense ; si la première moitié est ample, la seconde moitié doit être détaillée ; si un paragraphe est représentatif, le paragraphe suivant doit être abstrait ; une œuvre doit être aussi expressive qu'illustrative ».<ref>Liu Xie, cité dans Qi, Zhixiang (2024), p. 22.</ref> ==== Troisième forme : le cœur/esprit (心, ''xin'') ==== La troisième forme esthétique est le cœur/esprit (心, ''xin''). ''Xin'' se réfère au monde intérieur de l'esprit. L'esthétique chinoise traditionnelle considère les objets matériels qui représentent la beauté intérieure comme beaux. Ainsi, « la beauté du jade provient de cinq vertus » et « l'exquis des fleurs provient de son esprit ».<ref>Shao Yong, cité dans Qi, Zhixiang (2024), p. 5.</ref> Comme l'écrit Liu Zongyuan (773-819) : « La beauté n'est pas la beauté en soi ; elle n'est révélée que par l'esprit ».<ref>Liu Zongyuan, ''Journal on a Thatched Pavilion in Matui Mountain'', cité dans Qi, Zhixiang (2024), p. 5.</ref><ref>Ye, Lang (2021). « ''Beauty Lies in the Image'': Endowing Fundamental Theories of Aesthetics with Chinese Characteristics », dans Ghilardi, M. et Ram-Prasad, C. (éds.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, p. 47-65.</ref> Le concept de ''xin'' révèle l'esprit subjectif de l'esthétique chinoise traditionnelle, sa beauté idéale et son jugement de valeur. Dans la philosophie chinoise, ''xin'' (心) se réfère à la fois au « cœur » physique et à « l'esprit ». Traduit directement, ''xin'' désigne le cœur physique, bien qu'il se réfère aussi à « l'esprit », car les anciens Chinois croyaient que le cœur était le centre de la cognition humaine.<ref>Ghilardi, Marcello (2021). « ''Xiang'' (Image) and Painting », dans Ghilardi, M. et Ram-Prasad, C. (éds.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, sur l'écho du paysage avec le ''xin'' (cœur-esprit) du peintre.</ref> Cependant, l'émotion et la raison n'étaient pas considérées comme séparées, mais plutôt comme coextensives ; ''xin'' est autant cognitif qu'émotionnel, étant simultanément associé à la pensée et au sentiment. Pour ces raisons, il est souvent traduit par « cœur-esprit » (''heart-mind''). Cai Zong-qi insiste sur le fait que c'est précisément le ''xin'' (heart-mind) qui, dans l'esthétique des Six Dynasties, se trouve stimulé à l'expérience du paysage peint ou du poème.<ref>Bush, Susan (2004). « Essay on Painting by Wang Wei in Context », dans Cai, Zong-qi (éd.), ''Chinese Aesthetics'', op. cit., p. 73-74.</ref> La beauté est dans l'esprit : Les philosophes chinois traditionnels voient la beauté comme provenant de l'esprit-cœur (''xin'') ou du monde de l'esprit. Prenons deux exemples proéminents : l'appréciation du jade et des fleurs. Liu Xiang (77-6 avant notre ère) rapporte dans son ''Shuoyuan'' (說苑), recueil d'histoires confucéennes, les « six vertus-beautés » (六美, ''liu mei'') du jade attribuées à Confucius répondant à son disciple Zigong : « Le jade possède six vertus que les gentilshommes (君子, ''junzi'') apprécient : vu de loin, il est doux ; en s'en approchant, il est solide ; le son qu'il émet est calme et porte loin ; il est souple mais ne cède pas ; il est exquis mais non fragile ; il a des bords mais n'est pas tranchant ; il ne cache pas ses défauts. La douceur du jade est comparable à la vertu des gentilshommes, et sa solidité à leur érudition ; le son qu'il émet est comparable à leur chevalerie, et sa souplesse sans céder à leur courage ; l'exquis du jade est comparable à la bonté des gentilshommes, et son honnêteté avec ses défauts à la fiabilité des gentilshommes ».<ref>Liu Xiang, ''Shuoyuan'', chapitre 17 « Zayan », cité dans Qi, Zhixiang (2024), p. 27.</ref> Ces vertus sont toutes des esprits humanisés du jade. L'amour du jade dans la culture chinoise traditionnelle reflète l'esprit subjectif de la tradition esthétique. Un autre exemple est le poème de Shao Yong (1012-1077) « Sur l'appréciation des fleurs » qui voit la beauté idéale des fleurs dans l'esprit : « Ceux qui s'abandonnent à l'apparence des fleurs manquent la vraie beauté, / Ceux qui comprennent cela peuvent apprécier leur esprit. / Superficielle est leur apparence que le travail artificiel peut imiter, / La vraie merveille est l'esprit des fleurs qui n'est pas réplicable ».<ref>Shao Yong, cité dans Qi, Zhixiang (2024), p. 27.</ref> Le fondement culturel de la beauté de l'esprit : La culture chinoise traditionnelle voit l'esprit humain comme la substance ontologique de la beauté, qu'il s'agisse de beauté artistique ou de beauté naturelle. Cet esprit subjectif distingue la tradition esthétique chinoise de son homologue occidental.<ref>Qi, Zhixiang (2024), p. 33.</ref> Au cœur de la culture lettrée chinoise se trouve une attention soutenue au cœur-esprit et à sa transformation. Confucianisme, taoïsme et bouddhisme accordent tous une place importante à ce travail intérieur, sans pour autant le penser dans un cadre doctrinal commun : leurs conceptions du sujet, du monde et de la fin spirituelle restent profondément différentes. Le cœur du Confucianisme est la bienveillance (仁, ''ren''). Comme le dit Mencius : « La bienveillance concerne l'esprit humain ». L'école de la bienveillance est donc aussi l'école de l'esprit, dont le but est de cultiver le cœur qui aime les humains ainsi que soi-même.<ref>Discussion dans Qi, Zhixiang (2024), p. 33-35.</ref><ref>Lau, D. C. (trad.) (2004). ''Mencius'', New York: Penguin Books.</ref> Le Taoïsme révère la Voie du Ciel (天道, ''tiandao'') et préconise l'unité entre les humains et le Ciel, qui peut être atteinte en « laissant le cœur se reposer et l'esprit libre » et en préservant un cœur d'enfant. Le taoïsme invite ainsi à regarder vers l'intérieur, dans le cœur et l'esprit.<ref>Qi, Zhixiang (2024), p. 35.</ref> Le Bouddhisme, lorsqu'il fut introduit en Chine ancienne, absorba la tendance centripète de la structure clanique familiale et développa un accent sur l'esprit-cœur. L'école de Yogācāra d'Asie de l'Est (法相宗, ''Faxiang Zong''), la Conscience Seule, considère que « les trois royaumes sont dérivés de la source de l'esprit », et le Bouddhisme Chan soutient que « toutes choses sont dans ma propre source d'esprit ».<ref>Qi, Zhixiang (2024), p. 36.</ref> La valeur morale, l'orientation cognitive et la tendance esthétique à regarder vers l'intérieur et à voir le cœur comme la racine des choses sont au cœur de la culture chinoise traditionnelle. L'esprit-cœur humain est le centre autour duquel tout fonctionne. L'esprit subjectif qui voit la beauté de l'esprit fait partie de cette tradition culturelle.<ref>Qi, Zhixiang (2024), p. 36.</ref> ==== Quatrième forme : la Voie (道, ''dao'') ==== La quatrième forme esthétique est le Dao (道, la Voie). Dans les textes chinois, ''dao'' désigne tantôt une voie de conduite humaine, tantôt un ordre cosmique, tantôt une manière de s'accorder au cours des choses. Son usage esthétique varie selon les traditions : voie morale du gentleman confucéen, principe générateur des transformations chez les taoïstes, ou encore référence aux « principes célestes » (天理, ''tianli'') du néoconfucianisme. Dans tous ces cas, le Dao fonctionne comme un horizon normatif au regard duquel se mesure la valeur d'une œuvre ou d'une conduite, et donne à l'idéal de beauté sa portée éthique et cosmologique.<ref>Qi, Zhixiang (2024), p. 5.</ref> Le mot chinois ''dao'' (道) signifie une voie ou un chemin. Les Confucéens utilisaient le terme ''dao'' pour parler de la manière dont les êtres humains devraient se comporter en société.<ref>Ames, Roger T. (2021). « A Cosmological Aestheticism: The Interpretive Context for Confucian Ethics », dans Ghilardi, M. et Ram-Prasad, C. (éds.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, p. 67-92.</ref> Les Taoïstes, en revanche, conçoivent le Dao comme la réalité ultime et le principe cosmique qui sous-tend toutes choses.<ref>Chan, A. (2001). « Laozi », ''Stanford Encyclopedia of Philosophy''.</ref> Sur la place de la moralité (道德, ''daode'') dans la beauté, les écoles chinoises ne tiennent pas un discours uniforme. La tradition confucéenne, qui domine pour une large part la critique littéraire, picturale et calligraphique des lettrés, fait de la conduite vertueuse une dimension constitutive de la beauté humaine et sociale. Les courants taoïstes critiquent au contraire l'artifice des conduites codifiées, et opposent à la vertu rituelle la naturalité spontanée (自然, ''ziran'') : la « voie » qu'ils valorisent ne se confond donc pas avec la moralité confucéenne. Le mohisme, de son côté, se montre réservé envers la musique cérémonielle et le luxe rituel, qu'il regarde comme des dépenses contraires à l'utilité publique.<ref>Wang, Keping (2021), « A Sketch of Chinese Aesthetics », op. cit., section 3 « The Mohist Utilitarianism », p. 28-31, qui analyse en détail les chapitres ''Fei Yue'' (« Contre la musique ») du ''Mozi''. Voir aussi Wang, Keping (2009). « Mozi versus Xunzi on Music », ''Journal of Chinese Philosophy'', no 4.</ref> Le bouddhisme, enfin, distingue le plaisir esthétique de la libération du ''nirvāṇa'' et relativise la valeur des apparences au regard du chemin spirituel.<ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 160-193, sur la pénétration de l'esthétique chinoise par le bouddhisme Chan ; Sernelj, T. (2025). « The Beauty of Emptiness—The Foundational Root of Chinese Aesthetics », ''Asian Studies'', vol. 13, no 3, p. 71-93.</ref> Ces écoles convergent davantage sur l'idée que la beauté n'est pas une affaire purement formelle que sur le contenu de la « voie » qu'elles invoquent. C'est dans le confucianisme et les arts lettrés qui en relèvent que le rapprochement de la beauté et de la moralité est le plus systématiquement développé, et c'est principalement ce versant que les pages qui suivent décrivent.<ref>Qi, Zhixiang (2024), p. 36.</ref> Le terme ''daode'' (moralité) consiste en deux caractères : ''dao'' (道, voie/morale) et ''de'' (德, vertu). C'est un concept étroitement lié à la beauté. Les comportements inspirés par les cinq vertus, bienveillance (仁, ''ren''), droiture (義, ''yi''), bienséance (禮, ''li''), sagesse (智, ''zhi'') et fidélité (信, ''xin'' [à distinguer de 心 ''xin'', le cœur-esprit]), sont considérés comme beaux.<ref>Qi, Zhixiang (2024), p. 36-37.</ref> Bien que Confucius lui-même n'ait pas défini le concept de « beau » (美, ''mei''), le mot est utilisé plus de dix fois dans les ''Entretiens''. D'après la manière dont le mot est utilisé, on peut se faire une idée de la vision esthétique de Confucius. Premièrement, la beauté est ce qui plaît aux gens et leur apporte le bonheur. Il l'exprime en disant : « L'homme supérieur cherche à parfaire les qualités admirables des hommes et ne cherche pas à parfaire leurs mauvaises qualités ».<ref>''Entretiens'', 12:16, cité dans Qi, Zhixiang (2024), p. 37.</ref> Ici, le mot beauté (''mei'') est utilisé comme un nom, qui se réfère aux qualités vertueuses des personnes ; le mot ''mei'' est également utilisé en opposition au mal. Deuxièmement, entre la beauté de la forme et la beauté du contenu, Confucius considère cette dernière comme le facteur déterminant pour fixer la valeur esthétique des choses. Il l'indique en disant : « Ce sont les manières vertueuses qui constituent l'excellence (美, ''mei'') d'un voisinage ».<ref>''Entretiens'', 4:1, cité dans Qi, Zhixiang (2024), p. 37.</ref><ref>Wang, Keping (2021), « A Sketch of Chinese Aesthetics », op. cit., p. 21-24, sur la conception confucéenne du beau et du bien.</ref> Comme le commente le néo-confucéen Zhu Xi (1130-1200), la compréhension confucéenne de la beauté est que « la bonté est l'essence de la beauté » (善者美之質).<ref>Zhu Xi, ''Sishu Zhangju Jizhu'', cité dans Qi, Zhixiang (2024), p. 3, 37.</ref> Mencius (372-289 avant notre ère) affirme : « L'accomplissement moral est la beauté elle-même » (充實之謂美).<ref>Mencius, cité dans Qi, Zhixiang (2024), p. 3, 40.</ref><ref>Van Norden, B. W. (2004). « Mencius », ''Stanford Encyclopedia of Philosophy''.</ref> Xunzi (vers 310-235 avant notre ère) ajoute : « Si [la moralité d'un gentleman confucéen] est imparfaite ou impure, elle ne mérite pas le nom de beauté ».<ref>Xunzi, cité dans Qi, Zhixiang (2024), p. 3, 42.</ref><ref>Goldin, P. R. (2018). « Xunzi », ''Stanford Encyclopedia of Philosophy''.</ref> Pour le Taoïsme, l'ontologie préconise le non-être (無, ''wu'') comme beauté. Laozi enseigne : « Le grand son est imperceptible, la grande image est sans forme » (大音希聲,大象無形).<ref>''Daodejing'', chapitre 41, cité dans Qi, Zhixiang (2024), p. 44, 154.</ref><ref>Chan, Wing-tsit (1963). ''A Source Book in Chinese Philosophy'', Princeton, Princeton University Press, p. 160.</ref> Zhuangzi développe cette idée : « La grande beauté ne parle pas » (天地有大美而不言).<ref>Zhuangzi, cité dans Qi, Zhixiang (2024), p. 45, 155.</ref><ref>Li, Zehou (2010), ''The Chinese Aesthetic Tradition'', op. cit., p. 78-93.</ref> Le Bouddhisme situe la beauté dans le nirvana (涅槃, ''niepan''), l'état ultime de libération : « Le nirvana est appelé douce rosée » (甘露, ''ganlu''), symbolisant la beauté essentielle au-delà des apparences.<ref>Qi, Zhixiang (2024), p. 52, 260-261.</ref> ==== Cinquième forme : l'adéquation à la nature (適性, ''shixing'') ==== La cinquième forme esthétique est l'adéquation à la nature ou suivre la nature (適性, ''shixing''). Ce n'est que lorsque l'objet esthétique et le sujet se correspondent l'un à l'autre qu'il peut devenir l'objet précieux du plaisir, qu'il s'agisse de beauté formelle, spirituelle ou morale.<ref>Qi, Zhixiang (2024), p. 5.</ref> D'une part, la substance matérielle doit être saine pour la nature biologique du sujet ; d'autre part, le sujet doit également suivre la nature dotée des matériaux. Ce n'est que lorsque les choses et les humains se correspondent les uns aux autres qu'il peut y avoir unité entre le Ciel et l'humanité (天人合一, ''tianren heyi''), et cette beauté mutuellement bénéfique incarne l'esprit culturel de l'esthétique chinoise traditionnelle.<ref>Qi, Zhixiang (2024), p. 5.</ref> Le concept de ''shixing'' comporte deux dimensions principales : L'objet esthétique doit convenir à la nature humaine : Les philosophes chinois anciens soulignent que les objets de plaisir sensuel doivent être sains pour la nature humaine innée. Zuo Qiuming (vers 556-452 avant notre ère), historien contemporain de Confucius, insiste sur cette idée : « Quand la musique devient stridente ou la beauté visuelle aveuglante, leur beauté est perdue ».<ref>Zuo Qiuming, ''Guoyu'', cité dans Qi, Zhixiang (2024), p. 3, 53.</ref> Le ''Lüshi Chunqiu'' (呂氏春秋, ''Annales du Printemps et de l'Automne de Maître Lü'') met en garde : « Bien que nos oreilles aient soif de sons, nos yeux de couleurs, nos nez de senteurs, nos langues de saveurs, nous devons nous arrêter quand cela s'avère contraire à l'éthique pour nos vies. Par conséquent, les sages choisissent seulement de profiter des plaisirs sensuels qui sont bons pour la nature, et s'abstiennent de ce qui est mauvais pour la nature, et c'est ainsi que l'on protège notre nature innée ».<ref>''Lüshi Chunqiu'', sections ''Guisheng'' et ''Bensheng'', cité dans Qi, Zhixiang (2024), p. 3, 53.</ref> L'état naturel d'un objet crée la beauté : Le concept taoïste de « naturalité » (自然, ''ziran'') est central dans cette dimension de l'esthétique. Laozi enseigne que le Dao « modèle lui-même sur la naturalité » (道法自然). Ce principe influence profondément l'esthétique chinoise, où la spontanéité et l'absence d'artifice deviennent des critères de beauté.<ref>Qi, Zhixiang (2024), p. 53-66, 205-218.</ref><ref>Pohl, Karl-Heinz (2021). « Living and Dead Rules: The Role of Rules in Chinese Aesthetics », dans Ghilardi, M. et Ram-Prasad, C. (éds.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, sur la naturalité (''ziran'') et la règle (''fa'').</ref> Le peintre Zhang Zao (dynastie Tang) formule la maxime : « Au-dehors prendre la nature pour maître, au-dedans recueillir la source du cœur-esprit » (外師造化,中得心源), exprimant l'idéal d'une correspondance harmonieuse entre la nature extérieure et la nature intérieure du sujet.<ref>Zhang Zao, cité dans diverses sources dont Qi, Zhixiang (2024), p. 60.</ref> ==== Synthèse : l'interdépendance des cinq formes ==== Ces cinq formes esthétiques, la saveur, le motif/culture, le cœur/esprit, la Voie, et l'adéquation à la nature, constituent le courant principal de l'esprit esthétique traditionnel chinois, mais chacune présente des caractéristiques différentes dans les trois écoles de pensée : Confucianisme, Taoïsme et Bouddhisme. Les esthétiques confucéenne, taoïste et bouddhiste partagent des règles fondamentales mais adoptent des formes esthétiques diverses.<ref>Qi, Zhixiang (2024), p. 5-6.</ref> Le Confucianisme applique le principe de « comparaison de vertu » (比德, ''bide'') dans l'appréciation esthétique de la nature, et son appréciation du caractère humain met l'accent sur leur intégrité morale (風骨, ''fenggu''). Le Confucianisme voit l'harmonie équilibrée (中和, ''zhonghe'') comme l'état d'esprit idéal.<ref>Qi, Zhixiang (2024), p. 6.</ref><ref>Ames, Roger T. (2021), « A Cosmological Aestheticism », op. cit., p. 67-92, sur l'éthique cosmologique confucéenne et l'harmonie ''zhonghe''.</ref> Le Taoïsme, en revanche, préconise le non-être (無, ''wu'') comme beauté dans son ontologie. L'esthétique taoïste apprécie la subtilité et la simplicité, la naturalité et l'absence de but de la beauté. Le Taoïsme considère que la beauté devrait être autonome, libre et suivre la nature (適性, ''shixing'').<ref>Qi, Zhixiang (2024), p. 6.</ref> Le Bouddhisme, quant à lui, situe sa beauté ontologique dans l'idée du nirvana, le bonheur ultime (涅槃寂樂, ''niepan jile''). Son attitude envers la réalité est une affirmation négative : d'une part, la forme matérielle (色, ''rupa'') n'est pas différente du vide sans forme (空, ''śūnyatā'') ; d'autre part, toutes les choses visibles sont également différentes du vide.<ref>Qi, Zhixiang (2024), p. 6.</ref> Cette grille permet ainsi de montrer comment plusieurs traditions chinoises relient l'expérience des formes à la saveur, à l'écriture, au cœur-esprit, à la voie et à l'accord avec les transformations naturelles. Elle ne se substitue pas aux différenciations historiques et doctrinales entre confucianisme, taoïsme et bouddhisme, mais offre un point d'entrée pour les comparer. == Le Confucianisme et l'esthétique morale == === La bonté et la beauté === Dans la tradition confucéenne, la réflexion sur la beauté se développe en lien étroit avec celle sur la vertu, sans se confondre avec elle. Cette articulation, dont Confucius pose les premiers jalons et que Mencius puis Xunzi reprennent en l'infléchissant chacun à sa manière, constitue un trait durable de l'esthétique chinoise ancienne.<ref>Li, Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawai'i Press, p. 39-68.</ref><ref>Liu, Yuedi (2017). « Living Aesthetics in China: Confucian Aesthetics as a New Direction », dans Marcello Ghilardi et Chakravarthi Ram-Prasad (dir.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', Londres, Bloomsbury, chap. 1.</ref> ==== Confucius : la beauté et la bonté ==== Confucius (551-479 avant notre ère) ne propose pas de définition systématique du « beau » (美, ''mei''), mais le terme apparaît à plusieurs reprises dans les ''Entretiens'' (論語, ''Lunyu''). Son examen permet de reconstituer une vision cohérente.<ref>Confucius (2003). ''Analects: With Selections from Traditional Commentaries'', trad. Edward Slingerland, Indianapolis, Hackett Publishing.</ref> Premièrement, ''mei'' désigne souvent les qualités admirables d'une personne. Confucius déclare : « L'homme accompli (君子, ''junzi'') porte à l'achèvement les belles qualités (美, ''mei'') d'autrui et ne porte pas à l'achèvement ses mauvaises qualités » (''Entretiens'' 12.16). Le terme est ici employé en opposition au mal (惡, ''e''), dans un registre éthique autant qu'esthétique.<ref>''Entretiens de Confucius'' 12.16, traduction française d'après James Legge, ''The Chinese Classics'', vol. 1, Oxford, Clarendon Press, 1893.</ref> Deuxièmement, lorsqu'il s'agit de juger la qualité d'un voisinage, d'une œuvre ou d'une conduite, Confucius privilégie le contenu vertueux sur la forme : « Ce sont les manières humaines (仁, ''ren'') qui font la beauté (美, ''mei'') d'un voisinage » (''Entretiens'' 4.1).<ref>''Entretiens de Confucius'' 4.1.</ref> L'exemple le plus net se trouve dans la comparaison entre deux musiques rituelles. Confucius dit de la musique ''Shao'' (韶, attribuée aux rois vertueux Yao et Shun) qu'elle est « parfaitement belle (美, ''mei'') et parfaitement bonne (善, ''shan'') », mais de la musique ''Wu'' (武, célébrant les conquêtes du roi Wu de Zhou) qu'elle est « parfaitement belle, mais pas parfaitement bonne » (''Entretiens'' 3.25).<ref>''Entretiens de Confucius'' 3.25.</ref> La distinction, fine, mérite attention : Confucius ne refuse pas à la musique guerrière sa perfection formelle ; il y voit une beauté incontestable que la bonté n'épuise pas. La beauté et la bonté restent donc analytiquement séparables, même lorsque la pleine excellence requiert leur conjonction.<ref>Voir le commentaire de Li Zehou sur ce passage : « beauty and goodness » sont, pour Confucius, deux dimensions ordinairement liées dans la pratique rituelle, mais qui peuvent se dissocier ; Li (2010), p. 26-31.</ref> Le commentateur néo-confucéen Zhu Xi (1130-1200), dans ses ''Annotations rassemblées sur les Quatre Livres'' (四書章句集注, ''Sishu Zhangju Jizhu''), formule la lecture qui deviendra classique en commentant précisément ce passage sur la musique : « La beauté (美, ''mei'') est le déploiement sonore et formel ; la bonté (善, ''shan'') est la substance de la beauté » (美者,聲容之盛 ; 善者,美之實也).<ref>Zhu Xi, ''Sishu Zhangju Jizhu'' (四書章句集注), commentaire sur ''Entretiens'' 3.25, éd. Beijing, Zhonghua Shuju, 2012, p. 68.</ref> Il convient toutefois de noter que cette formule lapidaire, qui synthétise huit siècles de relecture confucéenne, durcit la position originelle de Confucius. Comme l'a souligné Li Zehou, l'identification pleine et entière de la beauté avec la bonté est davantage une construction Song-Ming, élaborée après l'absorption du bouddhisme Chan, qu'une thèse explicite des ''Entretiens''.<ref>Li (2010), p. 189-191 : « In addition, Zhang Heng sees this ideal as present in the primitive Confucianism of Confucius and Mencius, while I believe that Confucius and Mencius had only inklings of it. It was only as a product of Song-Ming neo-Confucian exegesis, following the absorption of Chan Buddhism, that the profound metaphysical significance of this ideal would be plumbed. »</ref> ==== Mencius : l'accomplissement moral et la beauté forte ==== Mencius (372-289 avant notre ère) prolonge la réflexion confucéenne en l'orientant vers une anthropologie morale. Pour lui, la beauté est inséparable de l'épanouissement de la personnalité, mais elle dépasse en même temps la simple bonté. ''Une fondation sensible commune.'' Mencius part d'une observation empirique : « Les bouches s'accordent sur les mêmes saveurs, les oreilles sur les mêmes sons, les yeux sur la même beauté. Les esprits seuls n'auraient-ils rien qu'ils approuveraient de manière commune ? Ce qu'ils approuvent en commun, ce sont les principes (理, ''li'') de notre nature et les déterminations de la droiture (義, ''yi'') » (''Mencius'' 6A.7).<ref>Mencius, ''Gaozi Shang'' (告子上, livre VI A), chapitre 7.</ref> La beauté n'est donc pas seulement objet du plaisir des sens, mais aussi de l'esprit, et la jouissance morale est de la même étoffe que la jouissance esthétique : « Les principes de notre nature et les déterminations de la droiture sont agréables à mon esprit, comme la chair d'animaux nourris d'herbe et de céréales est agréable à ma bouche » (''ibid''.).<ref>Mencius 6A.7.</ref> ''Une échelle de la personnalité accomplie.'' La formulation la plus dense se trouve dans le dialogue avec Haosheng Buhai au sujet de Yuezhengzi (''Mencius'' 7B.25). Mencius y déploie une échelle à six degrés : « Ce qui est désirable est appelé bon (善). Avoir cela en soi-même, on l'appelle véritable (信). La plénitude est appelée belle (美). Être empli et rayonner, on l'appelle grand (大). Être grand et transformer, on l'appelle sage (聖). Être sage et insaisissable, on l'appelle divin (神). »<ref>Mencius, ''Jinxin Xia'' (盡心下, livre VII B), chapitre 25. Traduction d'après Li (2010), p. 59.</ref> Loin d'identifier purement et simplement le beau et le bon, Mencius distingue la beauté (« plénitude », ''chongshi'' 充實) à la fois du « bon » (le désirable) et du « véritable » (avoir le bon en soi), et la place au-dessus de ces deux niveaux. La beauté inclut la bonté, mais la transcende : être beau, c'est avoir si pleinement absorbé les principes de l'humanité (仁) et de la droiture (義) qu'ils se manifestent naturellement dans la conduite, la tenue et les manières.<ref>Li (2010), p. 59-60 : « Beauty, then, is goodness completely worked out in the personality of the whole human being. It includes goodness but at the same time transcends it. »</ref> Au-dessus de la beauté, la « grandeur » désigne le rayonnement de cette plénitude ; la « sagesse » y ajoute la puissance transformatrice ; le « divin » désigne l'accomplissement insondable, sans effort apparent. Ces niveaux, comme le note Liu Yuedi, ne sont pas purement moraux mais portent une charge esthétique et téléologique.<ref>Liu (2017), section « A Further Enhancement of the Ideal » : « Noticeably, the level of 'beautiful' is not only distinguished from but also placed above the levels of 'good' and 'true'. »</ref> ''Le qi débordant et la beauté forte.'' Cette plénitude trouve son support psychophysique dans ce que Mencius nomme le ''haoran zhi qi'' (浩然之氣), le « souffle débordant ». « J'excelle à cultiver mon qi débordant. […] Ce qi est immensément vaste et puissant. Nourri avec intégrité et non altéré, il emplit ciel et terre » (''Mencius'' 2A.2).<ref>Mencius, ''Gongsun Chou Shang'' (公孫丑上, livre II A), chapitre 2.</ref> Le souffle moral, accumulé par la pratique constante de la droiture, devient une force sensible. C'est ce que Li Zehou appelle la ''yanggang zhi mei'' (陽剛之美), une beauté ferme, vigoureuse et dynamique, qu'il tient pour la première grande catégorie esthétique chinoise.<ref>Li (2010), p. 58-63. Pour Li, Mencius est le premier penseur chinois à formuler cette catégorie : « It was Mencius who first established the highest of Chinese aesthetic categories: ''yanggang zhi mei'', a virile, dynamic, and moral beauty, which might be considered to be the vital force of the moral subject. »</ref> Contrairement au sublime kantien, qui passe par la confrontation à une forme extérieure démesurée, la beauté forte mencéenne procède de la présentation directe d'une force morale subjective.<ref>Li (2010), p. 62 : « Whereas Kant's notion of the 'sublime' uses vast, unpleasant external form to manifest the triumph of morality and reason, Mencius' approach here is characterized by the use of a direct positive presentation of morality and reason to manifest the same. »</ref> ''Les quatre germes.'' L'ancrage de cette beauté morale dans la nature humaine repose sur la doctrine des « quatre germes » (四端, ''sì duān'') : le sentiment de commisération (惻隱之心), germe de la bienveillance (仁) ; le sentiment de honte et d'aversion (羞惡之心), germe de la droiture (義) ; le sentiment de modestie et de déférence (辭讓之心), germe des rites (禮) ; le sentiment d'approbation et de désapprobation (是非之心), germe de la sagesse (智) (''Mencius'' 2A.6).<ref>Mencius, ''Gongsun Chou Shang'', chapitre 6. Pour une analyse, voir « Mencius (Mengzi) », ''Internet Encyclopedia of Philosophy'', en ligne, consulté en 2025.</ref> Tout être humain disposant en lui-même de ces dispositions, l'éducation morale et esthétique est en principe ouverte à tous. ''Le plaisir partagé.'' La dimension politique de cette esthétique apparaît dans le dialogue avec le roi Xuan de Qi (''Mencius'' 1B.1). Mencius y compare trois manières de jouir de la musique : seul, avec quelques proches, ou avec le peuple. Le souverain digne, dit-il, est celui qui partage son plaisir avec ses sujets. La générosité du dirigeant et la qualité esthétique de son régime sont indissociables.<ref>Mencius, ''Liang Hui Wang Xia'' (梁惠王下, livre I B), chapitre 1.</ref> ==== La comparaison vertueuse (比德, ''bide'') ==== La pensée pré-Qin développe une technique d'expression appelée ''bide'' (比德), « comparaison de la vertu » : les éléments naturels deviennent les supports symboliques de qualités morales. Comme l'analyse Li Zehou, cette pratique constitue un stade intermédiaire entre l'imagerie magico-religieuse archaïque et le déploiement, beaucoup plus tardif, de la métaphore proprement poétique.<ref>Li (2010), p. 144-147.</ref> Confucius en offre la formulation classique : « L'homme de sagesse (智者, ''zhi zhe'') prend plaisir aux rivières, l'homme d'humanité (仁者, ''ren zhe'') prend plaisir aux montagnes ; l'homme de sagesse agit, l'homme d'humanité demeure tranquille ; l'homme de sagesse se réjouit, l'homme d'humanité atteint la longévité » (''Entretiens'' 6.23). Ici, l'eau évoque la mobilité de l'intelligence, la montagne la fermeté de la conscience morale.<ref>''Entretiens'' 6.23.</ref> Mencius reprend ce procédé en consacrant à l'eau plusieurs développements : « Il y a un art dans la contemplation de l'eau. Il faut la regarder dans ses vagues. Le soleil et la lune sont lumineux, et leur lumière pénètre les plus infimes ouvertures. L'eau qui s'écoule ne dépasse jamais un creux sans l'avoir empli ; de même, celui qui s'attache à la voie du sage ne se précipite pas à travers les leçons, mais en achève chacune avant de passer à la suivante » (''Mencius'' 7A.24).<ref>Mencius, ''Jinxin Shang'' (盡心上, livre VII A), chapitre 24.</ref> La persévérance et la rigueur progressive deviennent des qualités lisibles dans le comportement de l'eau. Le jade fournit un autre support privilégié. Le ''Liji'' (禮記, ''Livre des rites''), chapitre « Pin Yi » (聘義), met dans la bouche de Confucius un développement où l'on prête au jade onze vertus (humanité, sagesse, droiture, rites, etc.) en raison de ses propriétés physiques : sa chaleur au toucher, son éclat, sa résistance sans rudesse, sa résonance claire.<ref>''Liji'', chapitre « Pin Yi » (聘義). Voir aussi le ''Shuowen Jiezi'' de Xu Shen (vers 55-149), qui retient cinq vertus du jade ; cité dans Li (2010), p. 146.</ref> Une formulation parallèle se trouve dans le ''Guanzi'' (管子), chapitre « Shuidi » (水地, « L'eau et la terre »), où le jade incarne neuf qualités morales par ses caractéristiques sensibles.<ref>''Guanzi'', chapitre « Shuidi » (水地).</ref> Xunzi (vers 310-238 avant notre ère) systématise la pratique en comparant l'eau « à la vertu, à la droiture, à la voie, au courage et à la volonté ».<ref>Xunzi, chapitre « You Zuo » (宥坐), passage cité par Li (2010), p. 145.</ref> Dans un autre passage, recueilli au chapitre « Yao Wen » (堯問) du ''Xunzi'', Confucius répond à Zigong, qui s'inquiète de devoir servir un supérieur, en lui proposant la terre comme modèle : « Servir autrui, n'est-ce pas comme la terre ? Creusez-la, vous trouverez une source ; semez-y, les cinq céréales y pousseront ; arbres et herbes s'y multiplieront, oiseaux et bêtes s'y nourriront. On y vit, on y meurt. Elle prodigue ses bienfaits sans relâche. »<ref>''Xunzi'', chapitre « Yao Wen » (堯問).</ref> La terre symbolise ici l'inépuisable disponibilité du subalterne fidèle. Cette esthétique de l'analogie morale, comme le note Li Zehou, mobilise toujours la connaissance rationnelle pour appeler une résonance émotionnelle : les caractéristiques physiques d'un objet, connues par l'expérience commune, deviennent le support sensible d'une catégorie éthique.<ref>Li (2010), p. 146 : « In each case, what is clearly known by reason is used to establish or call forth an emotional homology. Emotions are constructed and shaped, in other words, through the mediation of reason. »</ref> ==== Xunzi : la perfection morale, condition de la véritable beauté ==== Plus exigeant que ses prédécesseurs sur le plan de la rectification morale, Xunzi soutient que « ce qui est imparfait et impur ne mérite pas le nom de beau » (凡不純粹者不得謂之美).<ref>Xunzi, chapitre 1 « Quan Xue » (勸學, « Exhortation à l'étude ») ; traduction anglaise dans Eric L. Hutton (trad.), ''Xunzi: The Complete Text'', Princeton, Princeton University Press, 2014, p. 13.</ref> ''Une beauté à deux niveaux.'' Le ''Xunzi'' reconnaît d'abord la puissance du désir sensible, que la tradition interprétative postérieure a souvent qualifié de premier niveau de beauté, sans que cette catégorisation soit explicitement formulée dans les passages eux-mêmes. La nature humaine inclut, selon lui, la recherche de cette satisfaction : « Les yeux désirent l'extrême en matière de visions, les oreilles en matière de sons, les bouches en matière de saveurs, les nez en matière d'odeurs, les corps en matière de confort. Ces cinq extrêmes, la disposition naturelle des gens ne peut éviter de les désirer » (''Xunzi'' 11).<ref>Xunzi, chapitre 11 « Wang Ba » (王霸, « Le roi véritable et l'hégémon ») ; trad. Hutton (2014), p. 92.</ref> Xunzi prend acte du fait que le désir humain est sans limite naturelle et que l'éliminer serait illusoire. ''L'équilibre par la réflexion.'' Comment dès lors résoudre la tension entre le désir illimité et la finitude des biens disponibles ? Par l'auto-régulation : « Bien que les désirs ne puissent être éliminés, lorsque ce qui est recherché n'est pas obtenu, l'homme réfléchi régulera sa recherche » (''Xunzi'' 22).<ref>Xunzi, chapitre 22 « Zheng Ming » (正名, « Rectification des noms ») ; trad. Hutton (2014), p. 244.</ref> Contrairement à Mencius, Xunzi tient la nature humaine pour mauvaise au sens où ses dispositions, livrées à elles-mêmes, produisent désordre et conflit. La cultivation par les rites, l'étude et la musique est donc indispensable.<ref>Sur la différence d'anthropologie entre Mencius et Xunzi, voir Li (2010), p. 65 : « Mencius can be said to have advanced the theory that human nature (in the form of social rationality) is good […]. Xunzi, on the other hand, advanced the theory that human nature (in the form of physical or animal sensuosity) is evil. »</ref> ''La beauté du gentilhomme.'' La beauté véritable, supérieure à celle des sens, est celle de la personnalité morale forgée par l'étude et l'effort : « Le gentilhomme (君子) sait que tout ce qui est imparfait et impur ne mérite pas le nom de beau. Il récite donc son apprentissage pour le maîtriser, le médite pour le comprendre, se conduit pour y demeurer, écarte ce qui le menace pour le nourrir. Finalement, le pouvoir et le profit ne peuvent l'ébranler, les masses ne peuvent le déplacer, et rien sous le ciel ne peut le secouer » (''Xunzi'' 1).<ref>Xunzi, chapitre 1 « Quan Xue » ; trad. Hutton (2014), p. 13.</ref> Cette stabilité morale, fruit d'un long travail sur soi, constitue pour Xunzi la beauté la plus haute. Elle se distingue, par sa genèse, de la beauté que Mencius rattache aux dispositions natives des « quatre germes » : pour Xunzi, la beauté du caractère n'est jamais donnée, toujours acquise par l'éducation. ''L'esprit pacifié, condition de la jouissance.'' L'éducation morale modifie en retour la perception du monde sensible. « Si le cœur est paisible et joyeux, alors même si les visions sont inférieures à l'ordinaire, elles suffisent à nourrir les yeux ; même si les sons sont inférieurs à l'ordinaire, ils suffisent à nourrir les oreilles. Les légumes et le ragoût suffisent à nourrir le palais ; les vêtements grossiers et les chaussures de fil grossier suffisent à nourrir le corps. Une cabane de chaume, des roseaux pour literie, une table basse et un tapis suffisent à nourrir la forme physique. Ainsi, même en manquant des meilleures des dix mille choses, on peut encore nourrir sa joie » (''Xunzi'' 22).<ref>Xunzi, chapitre 22 « Zheng Ming » ; trad. Hutton (2014), p. 247.</ref> La frugalité du gentilhomme n'est pas ascèse : elle est une forme de jouissance plus profonde, libérée de la dépendance à l'objet. ==== Synthèse : une articulation, non une fusion ==== La tradition confucéenne pré-impériale construit donc, plutôt qu'une équivalence pure et simple de la beauté et de la bonté, une articulation soigneusement modulée : * ''Dimension morale et expressive.'' La beauté la plus haute n'est pas une qualité formelle autonome, mais l'expression sensible d'une plénitude morale. Mencius la place toutefois au-dessus de la simple bonté, comme rayonnement de celle-ci dans le caractère intégral.<ref>Li (2010), p. 59-63 ; Liu (2017), section « A Further Enhancement of the Ideal ».</ref> * ''Dimension anthropologique.'' Pour Mencius, les dispositions morales natives (les « quatre germes ») rendent possible une beauté de l'accomplissement personnel. Pour Xunzi, c'est l'éducation des sens et des désirs, par les rites et la musique, qui rend possible la perception d'une beauté véritable. Les deux positions s'opposent sur l'origine, mais convergent sur la fonction médiatrice de la culture.<ref>Li (2010), p. 64-67.</ref> * ''Dimension éducative.'' L'étude des rites (禮, ''li'') et de la musique (樂, ''yue'') est solidaire de la cultivation morale. Confucius énonce ainsi la séquence : « Sois éveillé par la poésie, établi par les rites, accompli par la musique » (''Entretiens'' 8.8).<ref>''Entretiens'' 8.8.</ref> Cette triade restera la matrice de la pédagogie confucéenne.<ref>Liu (2017), section « Musical Performance and Rituals ».</ref> * ''Dimension symbolique.'' Le ''bide'' permet de lire dans les objets naturels (eau, montagne, jade, terre) le miroir de qualités morales, et de fonder ainsi une appréciation esthétique de la nature qui n'est pas purement contemplative.<ref>Li (2010), p. 144-147.</ref> Cette articulation se distingue des traditions qui séparent nettement esthétique et éthique. Comme l'a observé Haun Saussy, le terme chinois ''mei'' ne recouvre pas exactement le « beau » occidental hérité de Platon et de Kant ; il désigne plutôt une impression agréable d'ordre et d'harmonie, sans qu'on ait jamais composé en Chine impériale un traité systématique consacré à ''mei'' comme catégorie autonome.<ref>Saussy, Haun (1993). ''The Problem of a Chinese Aesthetic'', Stanford, Stanford University Press ; voir aussi Cai, Zong-qi (dir.) (2004). ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawai'i Press, « Prologue », p. 20-22.</ref> La pleine fusion métaphysique du beau et du bon, telle qu'elle s'exprime chez Zhu Xi, est l'aboutissement d'un long travail néo-confucéen qui intègre l'apport du Chan et du taoïsme, et que Confucius et Mencius n'avaient pas encore explicitement formulé.<ref>Li (2010), p. 190-191.</ref> === L'intégrité morale (風骨, ''fenggu'') === La catégorie de ''fenggu'' (風骨, littéralement « vent et os ») occupe une place centrale dans la critique littéraire et artistique chinoise des Six Dynasties et au-delà. Le terme désigne à la fois l'intégrité morale d'une personnalité et la vigueur d'une œuvre, qu'il s'agisse de littérature, de calligraphie ou de peinture.<ref>Qi, Zhixiang (2024). ''The Spirit of Traditional Chinese Aesthetics'', Shanghai/Singapour, Shanghai People's Publishing House / Springer Nature Singapore, p. 89-97.</ref> ==== Origine et composition du terme ==== ''Le contexte Wei-Jin.'' ''Fenggu'' émerge dans le vocabulaire critique sous les dynasties Wei et Jin (220-420), période marquée par l'effondrement de l'ordre confucéen Han et par l'essor du néo-taoïsme (玄學, ''Xuanxue''). C'est l'époque où la personnalité individuelle, sa physionomie spirituelle et sa singularité d'expression deviennent objets d'attention soutenue, comme en témoigne le ''Shishuo Xinyu'' (世說新語, ''Nouveaux récits des propos du monde'') compilé par Liu Yiqing (403-444).<ref>Sur la nouvelle sensibilité Wei-Jin et sa transposition de l'évaluation morale en évaluation esthétique, voir Lin, Shuen-fu (2004). « A Good Place Need Not Be a Nowhere: The Garden and Utopian Thought in the Six Dynasties », dans Cai (dir.), ''Chinese Aesthetics'', p. 135-137 ; Li, Wai-yee (2004). « Shishuo xinyu and the Emergence of Aesthetic Self-Consciousness in the Chinese Tradition », ''ibid.'', p. 237-269.</ref> ''Composition étymologique.'' Le caractère ''feng'' (風, « vent ») désigne d'abord, dans les sources Wei-Jin, l'allure spirituelle et le rayonnement d'une personne. Le ''Shishuo Xinyu'' use largement de composés tels que ''fengshen'' (風神, « esprit et manière »), ''fengqi'' (風氣, « atmosphère et souffle »), ''fengyun'' (風韻, « résonance de l'allure »), ''fengzi'' (風姿, « port et tenue »). Wang Yifu se décrit lui-même comme « d'un esprit et de manières extraordinaires » (風神英俊) ; Huan Yi loue Xie An en disant que « ce jeune homme a un esprit et des manières clairs et pénétrants » (此兒風神秀徹).<ref>Liu Yiqing, ''Shishuo Xinyu'', cité par Qi (2024), p. 89.</ref> ''L'os comme support métaphorique.'' Le terme ''gu'' (骨, « os ») désigne la structure intérieure, la charpente. Par analogie, on parle de l'« os » d'un caractère ou d'une œuvre : ce qui en constitue l'armature et la fermeté. Gu Kaizhi (顧愷之, vers 348-409), dans son ''Lun Hua'' (論畫, ''Sur la peinture''), parle déjà du « particulier de l'os » (骨法特奇, ''gufa te qi'') pour qualifier la facture intérieure d'un trait.<ref>Gu Kaizhi, ''Lun Hua'' ; voir Cai, Zong-qi (dir.) (2004), « Prologue », p. 16-18.</ref> Le composé ''fenggu'' unit ainsi le rayonnement perceptible (le « vent ») et l'armature interne (l'« os ») : la qualité spirituelle visible et la structure solide qui la soutient. ==== L'intégration confucéenne ==== ''Une catégorie composite.'' Bien que la sensibilité Wei-Jin soit marquée par le taoïsme philosophique et la recherche du détachement, ''fenggu'' ne s'oppose pas à l'éthique confucéenne. Des figures comme Xiang Xiu soutiennent que le ''mingjiao'' (名教, l'enseignement confucéen des noms) trouve son origine dans la nature, ce qui permet une intégration des deux traditions.<ref>Qi (2024), p. 90.</ref> Lorsque le confucianisme retrouve sa position dominante sous les Tang, la composante éthique de ''fenggu'' devient prépondérante. Ainsi, Wang Xizhi voit en Chen Xuanbo un homme « aux os droits » (正骨, ''zhenggu''), terme qui condense la rectitude morale. Chen Xuanbo, fonctionnaire des Jin de l'Ouest, était connu pour son intégrité (方正, ''fangzheng''), notion morale d'inspiration confucéenne.<ref>Liu Yiqing, ''Shishuo Xinyu'', chapitre « Shang Yu » (賞譽) ; cité par Qi (2024), p. 90.</ref> ''Liu Xie et la théorisation littéraire.'' La transposition systématique de ''fenggu'' dans la critique littéraire est l'œuvre de Liu Xie (vers 465-522). Dans le ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit de la littérature et la sculpture du dragon''), il consacre à cette catégorie un chapitre entier et la rattache aux poèmes ''feng'' (風) du ''Classique de la poésie'' (詩經, ''Shijing''), où s'exprime l'idéal d'éducation morale par le chant.<ref>Liu Xie, ''Wenxin Diaolong'', chapitre « Fenggu » (風骨). Pour une analyse classique du chapitre, voir Owen, Stephen (1992). ''Readings in Chinese Literary Thought'', Cambridge (Mass.), Harvard University Asia Center, p. 218-238 ; Cai, Zong-qi (dir.) (2001). ''A Chinese Literary Mind: Culture, Creativity, and Rhetoric in Wenxin Diaolong'', Stanford, Stanford University Press, en particulier Plaks, Andrew H., « The Bones of Parallel Rhetoric in ''Wenxin diaolong'' », p. 163-173.</ref> L'ouvrage de Liu Xie, comme le note Cai Zong-qi, marque l'aboutissement d'un effort de systématisation de la pensée littéraire amorcé sous les Qi et les Liang ; il code rhétorique et tropes selon une grille héritée du ''Yi jing'' et combine philologie classique et théorisation des genres.<ref>Cai, Zong-qi (2004), « Prologue », p. 14-16 et p. 23-26 ; sur la place du ''Wenxin Diaolong'' dans la production critique Qi-Liang, voir aussi Chang, Kang-i Sun, « Liu Xie's Idea of Canonicity », dans Cai (dir.) (2001), p. 17-31.</ref> ''Postérité dans la critique poétique.'' Lorsque le confucianisme reprend sa place centrale après les Tang, la lecture morale de ''fenggu'' prédomine. Chen Ziang (661-702) loue, dans sa ''Préface aux Bambous'' (修竹篇序), le ''fenggu'' des poètes Han et Wei ; Yin Fan, dans le ''Heyue Yingling Ji'' (河嶽英靈集), parle d'« avoir un caractère imposant » ; Yan Yu, dans le ''Canglang Shihua'' (滄浪詩話), loue « l'intégrité morale comme sous la dynastie Tang florissante ».<ref>Voir l'ensemble de ces citations dans Qi (2024), p. 91 ; pour Yan Yu, voir aussi Cai (dir.) (2004), p. 37.</ref> ==== Les dimensions de la beauté ''fenggu'' ==== ''Première dimension : l'engagement et l'intégrité.'' La beauté ''fenggu'' exprime d'abord l'engagement dans le monde et la fidélité au souverain, le souci du peuple et la responsabilité envers l'ordre politique du « monde sous le Ciel » (天下, ''tianxia''). Elle s'incarne dans des vers comme ceux de Chen Ziang : « Sentant les temps, je pense à servir la patrie ; je tire l'épée et m'élance hors des halliers » (感時思報國,拔劍起蒿萊).<ref>Chen Ziang, ''Ganyu Shi'' (感遇詩) ; cité par Qi (2024), p. 91.</ref> Ou dans ceux de Du Fu : « Toute l'année inquiet pour le peuple, mon cœur brûle au souvenir de ses souffrances » (窮年憂黎元,嘆息腸內熱).<ref>Du Fu, ''Zi Jing Fu Fengxian Xian Yong Huai Wu Bai Zi'' (自京赴奉先縣詠懷五百字) ; cité par Qi (2024), p. 91.</ref> La loyauté (忠, ''zhong'') et la droiture (義, ''yi'') sont, selon Ji Yun (1724-1805), les sources mêmes du ''fenggu'' : « La loyauté et la droiture croissent de l'esprit. L'intégrité morale croît de l'intérieur. »<ref>Ji Yun, ''Han Zhiyao Hanlin Ji Hou'' (韓志堯翰林集後) ; cité par Qi (2024), p. 92.</ref> ''Deuxième dimension : l'émotion directe et passionnée.'' ''Fenggu'' se caractérise par des émotions sans détour, sans réserve excessive. Le poète n'enveloppe pas son sentiment, il l'expose. Du Fu écrit : « Les larmes éclaboussent quand je ressens les temps ; mon cœur est saisi à la séparation, jusqu'à craindre le chant des oiseaux » (感時花濺淚,恨別鳥驚心).<ref>Du Fu, ''Chun Wang'' (春望) ; cité par Qi (2024), p. 92.</ref> Cao Zhi proclame : « Prêt à mourir pour la nation, je tiens la mort pour un retour chez moi » (捐軀赴國難,視死忽如歸).<ref>Cao Zhi, ''Baima Pian'' (白馬篇) ; cité par Qi (2024), p. 92. Sur Cao Zhi, voir Cutter, Robert Joe (2010). ''The Poetry of Cao Zhi'', Berlin, De Gruyter.</ref> À cette vigueur, le philosophe Zhu Guangqian (1897-1986) oppose l'idéal du ''pingdan'' (平淡, « fadeur ordinaire »), souvent rapproché d'une sensibilité taoïsante et lettrée, mais intégré à des milieux poétiques fort divers : « La beauté forte est dynamique ; la beauté douce est statique. »<ref>Zhu Guangqian, ''Wenyi Xinli Xue'' (文藝心理學), dans ''Zhu Guangqian Meixue Wenji'', vol. 1, Shanghai, Shanghai Literature and Art Publishing House, 1987 ; cité par Qi (2024), p. 92-93.</ref> Là où le ''pingdan'' aspire au détachement et à la sérénité, ''fenggu'' valorise un monde dynamique et passionné. Les poèmes de Cen Shen sur la frontière exemplifient ce monde en mouvement : « Le vent du nord souffle et brise l'herbe blanche ; en huitième mois, le ciel barbare est déjà couvert de neige. Soudain, comme une brise printanière nocturne, mille arbres, dix mille arbres, fleurissent en fleurs de poirier. »<ref>Cen Shen, ''Bai Xue Ge Song Wu Pan Guan Gui Jing'' (白雪歌送武判官歸京), trad. fr. d'après Qi (2024), p. 93.</ref> ''Troisième dimension : la vigueur structurelle.'' La beauté ''fenggu'' possède la vigueur du caractère, du trait et du timbre. Liu Xie décrit ses caractéristiques comme « solide et pratique, lumineuse et neuve » (剛健實踐,輝光日新), « pleine de vitalité » (生氣淋漓).<ref>Liu Xie, ''Wenxin Diaolong'', chapitre « Fenggu » ; cité par Qi (2024), p. 93-94.</ref> Une œuvre dépourvue de ''fenggu'' est dite « sans os » (無骨, ''wu gu'') ; une œuvre vigoureuse possède la « force des os » (骨力, ''guli''). Cette terminologie de la force constitue un répertoire critique stable : « os sévères » (剛骨, ''ganggu''), « caractère puissant » (雄風, ''xiongfeng''), « os extraordinaire » (奇骨, ''qigu''). Liu Xie résume : ''fenggu'' désigne « des manières fraîches et des os escarpés » (風清骨峻).<ref>Voir Qi (2024), p. 94-95 pour cette série d'expressions.</ref> ==== Personnalité et œuvre ==== ''Fenggu'', d'abord catégorie d'évaluation de la personnalité, devient avec Liu Xie une catégorie esthétique appliquée aux œuvres. Mais comme le souligne Ye Xie (1627-1703) dans son ''Yuan Shi'' (原詩, ''De la poésie''), « le fondement de la poésie réside dans le cœur de la personne » (詩本人心).<ref>Ye Xie, ''Yuan Shi'' ; cité par Qi (2024), p. 95.</ref> La beauté d'une œuvre demeure indissociable du caractère de son auteur. Le confucianisme classique exprime cette priorité par la formule « la voie est la racine, l'art la branche » (道本藝末).<ref>Voir Pei Xingjian, ''Wang Bo Zhuan'' (王勃傳), dans ''Jiu Tang Shu'' (舊唐書) ; cité par Qi (2024), p. 95.</ref> Sans fondation morale, l'art se réduit à la « sculpture d'insectes » (雕蟲小技, ''diaochong xiaoji''), virtuosité sans portée. C'est pourquoi de nombreux critiques font de ''fenggu'' le critère principal de la poésie : « En poésie, ''fenggu'' est l'élément principal » (詩以風骨為主), écrit Li Chonghua dans ses ''Zhenyi Zhai Shi Shuo'' (貞一齋詩說).<ref>Li Chonghua, ''Zhenyi Zhai Shi Shuo'' ; cité par Qi (2024), p. 95.</ref> Mao Xianshu (1620-1688) précise : « La poésie met l'accent sur ''fenggu'', pas seulement sur l'élégance littéraire » (詩重風骨,不專文采).<ref>Mao Xianshu, ''Shibian Di'' (詩辨坻) ; cité par Qi (2024), p. 95.</ref> L'évaluation critique mobilise ce critère pour distinguer les œuvres d'envergure : le ''Chu Ci'' (楚辭) a « un grand ''fenggu'' », selon Liu Xizai ; les poèmes de Cao Zhi ont « un caractère extraordinairement imposant et des couleurs littéraires luxuriantes » (骨氣奇高,詞采華茂), selon Zhong Rong dans le ''Shipin'' (詩品) ; Chen Boyu écrit avec « une force d'os puissante, des images vives et un sens profond » (骨力雄健,意象鮮明,色彩絢麗,寓意深遠), juge Mao Xianshu.<ref>Citations recueillies par Qi (2024), p. 95-96.</ref> ==== Le style poétique et l'effet d'ampleur ==== Au-delà de l'éthique personnelle, ''fenggu'' s'incarne dans un style. Les procédés caractéristiques sont les « mots francs » (言辭剛直, ''yanci gangzhi''), les « pinceaux comme des os » (用筆如骨), les « pics imposants de mots » (詞鋒崢嶸). Ces moyens donnent naissance à ce que Qi Zhixiang, dans une catégorie interprétative moderne, propose d'appeler un « sublime numérique » (數字的崇高, ''shuzi de chonggao''), c'est-à-dire un effet d'immensité produit par l'accumulation de grandeurs et d'images quantitatives.<ref>Qi (2024), p. 96-97. La catégorie est forgée par Qi pour rendre compte d'un effet stylistique constant des poèmes ''fenggu'' ; elle ne figure pas comme telle dans la critique traditionnelle.</ref> Li Bai en offre l'illustration célèbre dans ''Adieu au correcteur à la tour de Xie Tiao à Xuanzhou'' : « Les essais de Penglai ont les os de Jianan ; entre eux, le jeune Xie produit une note claire. Tous deux portent un élan tranquille et de grandes pensées qui s'envolent ; je voudrais monter au ciel bleu et saisir la lune lumineuse » (蓬萊文章建安骨,中間小謝又清發。俱懷逸興壯思飛,欲上青天攬明月).<ref>Li Bai, ''Xuanzhou Xie Tiao Lou Jianbie Jiaoshu Shu Yun'' (宣州謝朓樓餞別校書叔雲) ; cité par Qi (2024), p. 96.</ref> D'autres œuvres déploient cette ampleur. La chanson populaire ''Chilechuan'' (敕勒川) chante la steppe du nord : « Plaine de Chile, sous les monts Yin ; le ciel est comme une yourte qui couvre les quatre étendues sauvages. Le ciel est immense, la nature est vaste ; le vent souffle, l'herbe se courbe, on voit alors les vaches et les moutons » (敕勒川,陰山下。天似穹廬,籠蓋四野。天蒼蒼,野茫茫,風吹草低見牛羊). Wang Zhihuan, dans ''Le Pavillon de la Cigogne'' (登鸛雀樓), résume cette ambition d'élargissement : « Si l'on veut voir mille lis, il faut monter encore d'un étage » (欲窮千里目,更上一層樓).<ref>Citations dans Qi (2024), p. 97.</ref> ==== Un ensemble d'œuvres sous le signe de ''fenggu'' ==== On peut ainsi regrouper, dans une perspective critique, plusieurs œuvres et auteurs sous le signe de ''fenggu'' : les ''Chu Ci'', les poèmes de la période Jianan (avec Cao Cao, Cao Pi, Cao Zhi et les Sept Maîtres), Zuo Si, Chen Ziang, Du Fu, Gao Shi, Cen Shen, Wang Changling, Wang Zhihuan, Lu You, Xin Qiji. Ces auteurs forment un ensemble que la critique chinoise tient pour caractérisé par la fermeté intérieure et l'ampleur extérieure, sans qu'il faille y voir une école constituée et reconnue comme telle par tous les critiques chinois.<ref>Qi (2024), p. 97.</ref> Cette beauté ferme, comme l'analyse Li Zehou, prolonge sous une forme stylistique la ''yanggang zhi mei'' de Mencius : elle exprime l'idée qu'une force morale intériorisée peut se déployer dans une ampleur cosmique, sans passer par une séparation stricte entre monde humain et ordre naturel.<ref>Li (2010), p. 73-75.</ref> == Le Taoïsme et l'esthétique du non-être == === Le sublime dans le non-être (無, ''wu'') === Par contraste avec certaines traditions européennes qui ont privilégié la forme, la présence et la visibilité, une part importante des textes taoïstes et taoïsants valorise ce qui se dérobe, se retire ou demeure indéterminé : le silence en deçà des sons, la fadeur en deçà des saveurs, l'informe en deçà des contours. Le concept-clé en est ''wu'' (無), terme habituellement traduit par « non-être » ou « rien », mais qui désigne, dans le ''Laozi'' et le ''Zhuangzi'', moins une absence qu'une plénitude virtuelle, une réserve d'où surgissent toutes les déterminations. Cette orientation n'est pas un bloc homogène : elle traverse des œuvres et des écoles dont les positions varient sensiblement, du ''Daodejing'' au ''Xuanxue'' des Wei-Jin, du ''Huainanzi'' à la critique picturale lettrée. Les pages qui suivent en parcourent les principales articulations. Comme l'observe le philosophe Marcello Ghilardi, ''wu'' désigne le vide dans son rapport à la plénitude, l'absence comme corrélat d'un être-là (''you'') : « la vie se déploie ''entre'' l'occultation et la manifestation. ''Wu'' est à l'origine de toute forme et de toute image, c'est la matrice d'où chaque image-phénomène émerge et dans laquelle elle se dissout. Mais ''wu'' n'est pas l'origine absolue, le principe ou l'archè indépendant de toute plénitude. Il est au contraire conditionné, déterminé, relativisé par la plénitude ».<ref>Ghilardi, Marcello, ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', éd. Marcello Ghilardi et Chakravarthi Ram-Prasad, London, Bloomsbury, 2017, chap. 6, p. 110-111. Traduction nôtre.</ref> Le ''wu'' et le ''you'' sont co-dépendants, à la manière de l'encre et du papier, ou de la main et du cœur dans la peinture chinoise. ==== Laozi : le grand son est imperceptible, la grande image est sans forme ==== Le chapitre 41 du ''Daodejing'' (道德經, ''Livre de la Voie et de la Vertu'') condense en une formule l'intuition fondamentale : ''dayin xisheng, daxiang wuxing'' (大音希聲,大象無形), « le grand son est imperceptible, la grande image est sans forme ». L'idée n'est pas, comme on le croit parfois, que la beauté véritable serait invisible et inaudible. Elle est plus subtile. Toute forme déterminée est, par définition, une limitation : un son distinct, c'est ce son-ci et non un autre ; une image arrêtée, c'est cette figure-ci à l'exclusion des autres. Le « grand son » ou la « grande image » sont ceux qui n'ont pas choisi, qui demeurent dans la matrice d'où toutes les formes peuvent surgir. Wang Bi (王弼, 226-249), commentateur néo-taoïste du ''Daodejing'', éclaire cette idée. Selon lui, le Dao est sans forme et sans nom : ''« le temps avant qu'il n'y ait aucune forme ni aucun nom est le commencement des dix mille choses [...] Le Dao, parce qu'il est sans forme et sans nom, est ce qui donne naissance et porte à l'achèvement les dix mille choses »''.<ref>Wang Bi, commentaire au chapitre 1 du ''Daodejing'', cité dans Shuen-fu Lin, « A Good Place Need Not Be a Nowhere », dans Zong-qi Cai (éd.), ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawai'i Press, 2004, p. 137-138. Traduction adaptée de Richard J. Lynn, ''The Classic of the Way and Virtue'', New York, Columbia University Press, 1999, p. 51.</ref> Le ''wu'' n'est pas un néant : « on voudrait dire qu'il n'existe pas, mais les choses parviennent à l'existence grâce à lui ; on voudrait dire qu'il existe, mais nous n'en voyons pas la forme. C'est pourquoi le texte parle de "forme de ce qui n'a pas de forme, image de ce qui n'a pas d'existence sensible" ».<ref>Wang Bi, commentaire au chapitre 14 du ''Daodejing'', dans Lin, ''art. cit.'', p. 138.</ref> Ce que dit Wang Bi, c'est qu'on ne doit pas confondre le non-être taoïste avec le néant absolu. Il s'agit plutôt d'un état antérieur à toute distinction, d'une virtualité féconde. Le chapitre 14 du ''Daodejing'' le décrit par trois négations : on le regarde sans le voir, on l'écoute sans l'entendre, on le palpe sans le toucher. Il échappe simultanément aux trois sens majeurs. Ces trois aspects fusionnent en une seule unité, que Laozi nomme ''xuan'' (玄), « mystérieux », et ''da'' (大), « grand », parce qu'il enveloppe toutes choses sans s'identifier à aucune. ==== Zhuangzi : la grande beauté du Ciel et de la Terre ==== Zhuangzi (莊子, vers 369-286 avant notre ère) approfondit l'intuition de Laozi et la prolonge dans le domaine esthétique. Le chapitre ''Zhibeiyou'' (知北遊, « La connaissance errant vers le Nord ») contient l'une des phrases les plus célèbres de l'esthétique chinoise : ''tiandi you damei er buyan'' (天地有大美而不言), « le Ciel et la Terre ont une grande beauté mais ne la disent pas ». Les quatre saisons ont des lois manifestes mais n'en discutent pas ; les dix mille choses ont des principes d'accomplissement mais ne les expliquent pas. Cette phrase a une portée philosophique majeure, dont Li Zehou éclaire l'enjeu. Là où Xunzi, dans la tradition confucianiste, affirmait que ''« sans l'artifice, la nature ne pourrait s'embellir elle-même »'', Zhuangzi soutient la thèse inverse : c'est précisément parce que le Ciel et la Terre « ne parlent pas » qu'ils sont beaux ; c'est parce qu'aucun artifice humain ne s'y mêle qu'ils possèdent la « grande beauté ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawai'i Press, 2010, p. 77, 88-89.</ref> L'opposition est nette : pour les confucéens, la beauté requiert l'effort humain, le rite, la mise en forme ; pour Zhuangzi, la beauté authentique est celle qui n'a besoin de personne pour exister, celle qui est ''ziran'', « ainsi de soi-même ». L'idéal esthétique qui en découle modifie la notion même de sujet contemplant. Comme l'écrit Li Zehou, là où l'attitude confucianiste maintient l'homme comme maître de la nature (le sage « prend plaisir aux rivières, prend plaisir aux montagnes »), Zhuangzi inverse le rapport : la vastitude de la nature surpasse l'insignifiance du monde humain. ''« Combien est sans bornes la beauté de la nature, combien incertaine la vie humaine »'' : ce dicton chinois exprime un sentiment qui marquera durablement la sensibilité des lettrés et la poésie de paysage.<ref>Li Zehou, ''op. cit.'', p. 94-95.</ref> Zhuangzi pousse jusqu'à ses conséquences l'idée d'une beauté indépendante du sensible. Dans le chapitre ''Zhile'' (至樂, « Le bonheur parfait »), il oppose le bonheur du monde (richesses, honneurs, plaisirs sensuels) à un bonheur d'un autre ordre : ''zhile wule'' (至樂無樂), « le bonheur ultime est non-bonheur ». La formule est paradoxale, comme souvent chez Zhuangzi, mais son sens devient clair lorsqu'on la rapproche de l'idée du « grand son imperceptible ». Le bonheur ultime n'est pas une intensification du plaisir : c'est un état où la dépendance même à l'égard du plaisir extérieur s'est dissoute. Il consiste, comme dit Zhuangzi, à « ne rien faire pour obtenir le plaisir », ce que la plupart des gens prennent pour un grand mal et ce que le sage considère comme le plus grand des biens. ==== Le ''Lüshi chunqiu'' et le ''Huainanzi'' : la saveur de l'insipide ==== L'idée d'une beauté du non-être se diffuse, sous les Qin et les Han, dans des œuvres syncrétiques. Le ''Lüshi chunqiu'' (呂氏春秋, ''Printemps et Automnes de Lü Buwei''), compilé vers 239 avant notre ère sous l'égide du chancelier Lü Buwei, transpose cette esthétique dans le registre politique : seule la personne capable de « sentir l'invisible, d'entendre l'inaudible et de saisir l'indescriptible » peut être dite connaître le Dao. Le ''Huainanzi'' (淮南子), composé sous la direction de Liu An (劉安, vers 179-122 avant notre ère), prince de Huainan, va plus loin. Le chapitre 1, ''Yuandao xun'' (原道訓, « Traité sur l'origine, le Dao »), pose que ''« la vie émerge du non-être, la réalité émerge du vide »'' (生乎無,實乎虛).<ref>Liu An (dir.), ''Huainanzi'', chapitre 1, ''Yuandao xun''. Pour le texte chinois et une traduction anglaise complète, voir John S. Major, Sarah A. Queen, Andrew Seth Meyer et Harold D. Roth (trad.), ''The Huainanzi: A Guide to the Theory and Practice of Government in Early Han China'', New York, Columbia University Press, 2010, chap. 1.</ref> Les couleurs émergent de l'absence de couleur, la musique émerge du silence, les saveurs émergent de la fadeur. Le texte tire de ce principe une conséquence esthétique : la beauté de la forme est limitée, tandis que celle de l'informe ne l'est pas. Les objets sensibles du plaisir, plats raffinés, vêtements brodés, musiques touchantes, sont des supports, non des fins. ''« Ce qui est sans son est ce qui est véritablement audible, et ce qui est sans goût est ce qui est véritablement savoureux »'' (故無聲者可聽,無味者可嘗).<ref>''Huainanzi'', chapitre 1, ''Yuandao xun'', dans Major et al. (trad.), ''op. cit.'' L'idée est reprise et développée par le chapitre 7, ''Jingshen xun'' (精神訓, « Traité sur l'essence spirituelle »).</ref> Cette idée de la fadeur (淡, ''dan'') comme saveur suprême connaîtra une longue postérité dans l'esthétique chinoise. Li Zehou montre comment elle devient, à partir des Tang, le critère majeur de l'appréciation poétique et picturale. Mei Yaochen (1002-1060), poète des Song, l'a résumée en une formule : « rien n'est aussi difficile, en poésie ancienne ou moderne, que le simple et le fade ». Su Shi (1037-1101) la reprend : « lorsqu'on commence à écrire, on vise l'atmosphère extraordinaire et la couleur éclatante ; mais en mûrissant on commence à viser le fade et le simple ».<ref>Li Zehou, ''op. cit.'', p. 177. La traduction française rend ''dan'' (淡) par « fade » et « bland » par « insipide » ; nous suivons ici la convention sinologique française, en particulier l'usage qu'en fait François Jullien, ''Éloge de la fadeur. À partir de la pensée et de l'esthétique de la Chine'', Paris, Philippe Picquier, 1991.</ref> ==== Le Xuanxue : l'être pensé à partir du non-être ==== Sous les Wei et les Jin (220-420), le ''Xuanxue'' (玄學, traduit habituellement par « étude du mystérieux » ou « néo-taoïsme », parfois « apprentissage abscons ») élabore une véritable métaphysique du ''wu''. Le mouvement réunit Wang Bi (226-249), He Yan (mort en 249), Guo Xiang (mort en 312), et constitue, selon Zong-qi Cai, le cadre intellectuel central pour l'esthétique des Six Dynasties.<ref>Zong-qi Cai, « Prologue », dans ''Chinese Aesthetics'', op. cit., p. 1-3, 8-9.</ref> La thèse centrale de Wang Bi peut s'énoncer ainsi : ''yi wu wei ben'' (以無為本), « prendre le non-être pour racine ». Tous les êtres dérivent du non-être ; le non-être est leur fondement. Mais Wang Bi précise aussitôt que la relation entre les deux n'est pas celle d'une création temporelle : il s'agit plutôt d'un rapport de substance (體, ''ti'') à fonction (用, ''yong''). Son commentaire au chapitre 11 du ''Daodejing'' fournit l'analogie classique. Lorsqu'on fabrique une roue, un récipient ou une chambre, ce qui rend l'objet utilisable n'est pas le bois, l'argile ou les murs, mais bien le vide qui s'y trouve. Comme le commente Wang Bi : ''« que le bois, l'argile et le mur puissent former ces trois choses [roue, vase, chambre], cela dépend dans chaque cas du fait d'atteindre la fonctionnalité à travers le rien »''.<ref>Wang Bi, commentaire au chapitre 11 du ''Daodejing'', cité dans Lin, ''art. cit.'', p. 138-139.</ref> L'enjeu n'est pas seulement métaphysique : il est esthétique. Si le non-être est ce qui rend possible toute fonction, alors la beauté véritable d'une œuvre d'art ne tient pas seulement à ce qu'elle montre, mais à ce qu'elle ménage de vide, à l'espace qu'elle laisse à l'imagination du spectateur. C'est cette idée qui informera, sous une forme ou une autre, toute la peinture de paysage chinoise, où les zones non peintes du rouleau jouent un rôle aussi important que les zones travaillées. Tous les Wei-Jin ne suivent pas Wang Bi. Guo Xiang, dans son commentaire sur le ''Zhuangzi'', conteste l'antériorité du non-être : pour lui, ''wu'' signifie simplement « rien » et ne saurait engendrer ''you''. Les choses se génèrent elles-mêmes (''zisheng'', 自生) ; elles sont « ainsi de soi-même » (''ziran'', 自然) sans cause extérieure.<ref>Guo Xiang, commentaire au chapitre « Qiwulun » du ''Zhuangzi'', cité dans Lin, ''art. cit.'', p. 140-141.</ref> La controverse entre les partisans du non-être (''guiwu'') et ceux de l'être (''chongyou''), formalisée par Pei Wei (267-300) dans son ''Chongyou Lun'' (崇有論, « De la valorisation de l'être »), structurera durablement la pensée chinoise médiévale. ==== Les expressions artistiques du non-être ==== L'esthétique du ''wu'' n'est pas restée spéculative. Elle a informé tous les arts chinois et leur a donné certains de leurs traits les plus reconnaissables. ''La beauté du silence.'' Là où Laozi affirmait que « le grand son est imperceptible », plusieurs lettrés des Wei-Jin ont fait du silence un objet esthétique à part entière. Ruan Ji (阮籍, 210-263), théoricien de la musique, écrit dans le ''Qing si fu'' : ''« les formes que l'on peut voir ne sont pas les plus belles des visions, et les notes que l'on peut entendre ne sont pas la plus fine des musiques »''.<ref>Ruan Ji, ''Qing si fu'', cité et commenté par Ronald Egan, « Nature and Higher Ideals », dans Zong-qi Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 296-297.</ref> Le préambule poétique de Ruan Ji aboutit à une thèse précise : il faut un « mystère caché sans forme » et une « tranquillité parfaite sans bruit » pour qu'apparaisse la véritable pureté. La légende veut que Tao Yuanming (陶淵明, 365-427) possédait une cithare ''guqin'' (古琴) sans cordes. Chaque fois qu'il avait du vin, il caressait l'instrument muet et exprimait par ses gestes ce qu'aucune corde n'aurait rendu.<ref>L'anecdote, rapportée dans le ''Song Shu'' de Shen Yue, est devenue l'un des emblèmes de l'esthétique du silence. Voir Kang-i Sun Chang, « Tao Qian and the Indeterminacy of Interpretation », dans Zong-qi Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 169-189.</ref> L'anecdote suggère que la musique la plus haute réside moins dans le son produit que dans la disposition intérieure qui le rend possible. ''La beauté de l'absence de forme.'' En peinture, l'idéal d'« aller au-delà de l'image » (象外, ''xiangwai'') s'installe dès les Wei-Jin. Xie He (謝赫, actif vers 500-535), peintre et critique, formule dans son ''Guhua Pinlu'' (古畫品錄) les « six règles » (六法, ''liufa'') qui deviendront le code de la critique picturale chinoise. La première de ces règles, ''qiyun shendong'' (氣韻生動), « résonance spirituelle, mouvement vivant », exige que la peinture rende le souffle vital plutôt que l'apparence extérieure.<ref>Sur les six règles de Xie He, voir Yolaine Escande, dans ''The Bloomsbury Research Handbook'', op. cit., note 2 du chapitre sur la calligraphie ; et le commentaire de Marcello Ghilardi, ''ibid.'', chap. 6.</ref> L'image, ici, ne vaut pas pour ce qu'elle montre, mais pour ce qu'elle suggère au-delà d'elle-même. ''Le non-agir et la beauté.'' Sur le plan éthique, le ''wuwei'' (無為, « non-agir » ou « agir sans intervenir ») devient un idéal de vie autant qu'un idéal artistique. Les lettrés des Wei-Jin, traumatisés par les guerres et les exécutions politiques (Ji Kang fut décapité en 262), se réfugient dans une esthétique de la retraite, du jardin, de la conversation pure (''qingtan'', 清談).<ref>Sur le contexte politique et l'émergence du ''qingtan'', voir Wai-yee Li, « Shishuo Xinyu and Aesthetic Self-Consciousness in the Chinese Tradition », dans Zong-qi Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 237-270.</ref> Le sage taoïste, qui « ne fait rien et tout est fait », sert de modèle à une éthique de la non-intervention qui se prolonge dans l'art : le coup de pinceau réussi est celui qui paraît être venu de lui-même, sans effort visible. ==== La limite du sensible et l'ouverture de l'infini ==== L'esthétique du non-être n'est pas une dévaluation du sensible. Elle pose au contraire une question subtile : comment le sensible peut-il s'ouvrir à plus que lui-même ? Zhuangzi, dans un passage célèbre du chapitre ''Tiandi'' (天地), prévient contre l'excès sensoriel : ''« les cinq couleurs confondent les yeux et les rendent moins perçants ; les cinq sons musicaux confondent les oreilles et les rendent moins fines ; les cinq saveurs gâtent la bouche et la rendent moins sensible »''. Ce n'est pas le sensible qui est en cause, mais sa saturation. Une oreille assaillie de bruits ne distingue plus rien ; une bouche habituée aux saveurs fortes ne perçoit plus les nuances. La proposition esthétique qui s'en dégage est précise. Pour entendre véritablement la musique, il faut savoir entendre le silence qui la borde. Pour goûter véritablement une saveur, il faut être capable d'apprécier la fadeur. Pour voir véritablement une peinture, il faut percevoir l'invisible qu'elle suggère. Le ''wu'' n'est pas l'opposé du ''you'' : il en est la condition de possibilité, l'horizon qui empêche le sensible de se refermer sur lui-même. On peut, par analogie, parler à ce propos d'un « sublime du non-être ». La catégorie est moderne et n'appartient pas au vocabulaire chinois ancien, qui ne pense pas le sublime au sens où l'entendent Burke ou Kant ; elle sert ici à nommer une orientation où la beauté infinie du Dao se laisse pressentir dans l'absence, le silence, la fadeur et l'informe. Cette orientation a marqué durablement la peinture lettrée, la calligraphie, la poésie et l'art des jardins en Chine, et continue, par l'intermédiaire de François Cheng, François Jullien et de quelques autres, de nourrir la réflexion esthétique contemporaine. === Le mystère et la subtilité (玄妙, ''xuanmiao'') === Deux notions étroitement liées, le mystère (玄, ''xuan'') et la subtilité (妙, ''miao''), forment ensemble le composé ''xuanmiao'' (玄妙), qui désigne l'horizon ultime de l'esthétique taoïste. Le terme est difficile à traduire : « mystérieux et subtil » en rend l'orientation générale, mais perd la richesse sémantique de l'original. ''Xuan'' évoque la profondeur obscure, la couleur sombre du ciel nocturne ; ''miao'' évoque le merveilleux qui échappe au discours. Combinés, ils désignent la qualité de ce qui est à la fois infiniment profond et ineffablement délicat. ==== La subtilité (妙, ''miao'') : le merveilleux au-delà de la forme ==== Le caractère ''miao'' n'apparaît pas dans le ''Shuowen jiezi'' (說文解字), le premier dictionnaire étymologique chinois (vers 100 de notre ère). Cette absence invite à la prudence dans l'analyse étymologique : on ne peut en déduire grand-chose à elle seule. En revanche, l'usage philosophique et critique du terme se développe nettement dans les textes pré-Han et Han : ''Daodejing'', ''Lüshi chunqiu'', ''Shiji'' de Sima Qian, ''Hanshu'' de Ban Gu. Le chapitre 1 du ''Daodejing'' contient l'occurrence canonique : ''« toujours sans désir, nous devons être trouvés si nous voulons sonder son profond mystère [妙, miao] ; mais si le désir est toujours en nous, sa frange extérieure est tout ce que nous verrons. Sous ces deux aspects, il est essentiellement le même, mais à mesure que le développement se produit, il reçoit des noms différents. Ensemble, nous les appelons le mystère [玄, xuan], et le mystère est le portail de tout ce qui est subtil et merveilleux »''.<ref>Laozi, ''Daodejing'', chapitre 1, dans la traduction de Richard J. Lynn, ''The Classic of the Way and Virtue'', op. cit., p. 51.</ref> Le texte original (玄之又玄,眾妙之門, ''xuan zhi you xuan, zhong miao zhi men'') établit dès le premier chapitre le lien étroit entre ''xuan'' et ''miao'' : le mystère est le portail par lequel s'ouvre l'accès à toutes les subtilités. Le commentaire de Wang Bi précise que ''miao'' désigne « la subtilité ultime » (至妙, ''zhi miao''), ce qui se dérobe à la saisie discursive parce que cela précède toute distinction conceptuelle. Dans la pratique du ''Daodejing'', ''miao'', ''xuan'' et ''wei'' (微, « subtil ») sont parfois interchangeables, et apparaissent souvent groupés dans des composés : ''xuanmiao'', ''weimiao'' (微妙, « subtil et mystérieux »). ==== De l'usage philosophique à la critique esthétique ==== Sous les Han (206 avant notre ère - 220 de notre ère), ''miao'' migre du registre cosmologique vers le registre critique. Ban Gu (32-92), dans la préface qu'il rédige pour le ''Li Sao'' (離騷, « Encountering Sorrow ») de Qu Yuan, qualifie celui-ci de ''miaocai'' (妙才), « talent de subtilité ». L'expression ''yanyu miao tianxia'' (言語妙天下), « la parole subtile à travers le monde », sert à louer l'éloquence. Liu Shao, dans la ''Renwu Zhi'' (人物志, « Annales des personnages »), utilise ''miao'' pour caractériser certains individus : ''« les personnes particulièrement subtiles possèdent une substance intérieure exquise sans embellissement extérieur »''. Le ''Huainanzi'' conserve quant à lui un usage cosmologique du terme : ''« la correspondance mutuelle entre les objets est mystique et insondable, au-delà de la compréhension et de l'analyse »'' (萬物相應,玄妙莫測). Dong Zhongshu (董仲舒, vers 179-104 avant notre ère), théoricien du système de la résonance entre Ciel et Homme, parle d'une logique du yin et du yang qui est ''« subtile et exquise, sans que l'on puisse en pénétrer la raison »'' (陰陽之理,妙而不可知). ==== L'épanouissement sous les Wei et les Jin ==== C'est sous les Wei et les Jin (220-420) que ''miao'' devient pleinement une catégorie esthétique. Les milieux lettrés qui pratiquent la « conversation pure » (''qingtan'') et l'« étude du mystérieux » (''Xuanxue'') font du terme un instrument privilégié de l'appréciation. Ils l'appliquent à la peinture, à la poésie, à la calligraphie, à la musique et à la danse, mais aussi aux phénomènes naturels et aux attributs des personnes. L'anecdote la plus célèbre concerne Gu Kaizhi (顧愷之, vers 348-409), l'un des fondateurs de la peinture chinoise de figure. Il passait, dit-on, plusieurs années avant de peindre les yeux de ses sujets. Lorsqu'on l'interrogeait sur cette lenteur, il répondait que la beauté des membres ne réside pas dans leur perfection physique mais dans leur capacité à manifester l'essence de l'âme ; et cette essence, ajoutait-il, « ne peut se transmettre par les mots ».<ref>L'anecdote est rapportée dans le ''Shishuo xinyu'' (世說新語) de Liu Yiqing, chapitre ''Qiaoyi''. Voir Liu Yiqing, ''A New Account of Tales of the World'', trad. Richard Mather, 2e éd., Ann Arbor, University of Michigan Press, 2002.</ref> La calligraphe Wei Shuo (衛鑠, 272-349), connue sous le titre de « Madame Wei » et préceptrice du jeune Wang Xizhi, formule dans le ''Bi Zhen Tu'' (筆陣圖, « Schéma du déploiement du pinceau ») une idée parente : la calligraphie atteint son niveau le plus élevé lorsqu'elle parvient à transmettre la subtilité des formes naturelles. L'usage critique de ''miao'' atteste, selon Li Zehou, une transformation majeure de la sensibilité esthétique chinoise : le glissement de la beauté formelle, fondée sur la régularité et le décorum confucéens, vers une beauté de la suggestion, de l'au-delà des formes, qui sera caractéristique de tout l'art lettré ultérieur.<ref>Li Zehou, ''op. cit.'', chapitre 3, « The Daoist-Confucian Synthesis », et chapitre 4, « Beauty in Deep Emotion », p. 76-141.</ref> ==== La critique calligraphique sous les Tang ==== Sous les Tang (618-907), le terme ''miao'' acquiert sa systématicité de catégorie critique. Yu Shinan (虞世南, 558-638), au début de la dynastie, consacre dans son ''Bisui Lun'' (筆髓論, « De l'essence du pinceau ») une section intitulée ''Qi miao'' (契妙, « Saisir la subtilité »). Il y affirme que ''« le Dao de la calligraphie réside dans le royaume du mystérieux et du subtil [玄妙], qui ne peut être atteint que par un dévouement concentré et une compréhension profonde des subtilités de l'art »''.<ref>Yu Shinan, ''Bisui Lun'', dans Huang Jian (éd.), ''Anthologie des traités de calligraphie des dynasties successives'', Shanghai, Shanghai shuhua chubanshe, 1979, vol. 1, p. 110-111.</ref> Mais c'est Zhang Huaiguan (張懷瓘, actif vers 713-741) qui systématise l'usage. Dans son ''Shuduan'' (書斷, « Évaluation de la calligraphie »), il distingue trois rangs pour les œuvres de première classe : les œuvres divines (神品, ''shenpin''), les œuvres profondes (妙品, ''miaopin''), et les œuvres habiles (能品, ''nengpin''). La hiérarchie n'est pas indifférente : ''shenpin'' désigne ce qui semble fait par les dieux, au-delà de toute règle ; ''miaopin'' désigne ce qui, tout en restant accessible à l'analyse, atteint un degré de subtilité qui échappe à la compréhension ordinaire ; ''nengpin'' désigne la maîtrise technique sans la profondeur.<ref>Sur Zhang Huaiguan et son système de classement, voir Yolaine Escande, « Tang Dynasty Aesthetic Criteria: Zhang Huaiguan's ''Shuduan'' », ''Journal of Chinese Philosophy'', vol. 41, issues 1-2, mars-juin 2014, p. 148-169.</ref> Zhang précise ce qu'il entend par ''miaopin'' : ''« les chefs-d'œuvre profonds en calligraphie et en littérature doivent contenir des implications profondes. Les idées profondes [玄妙] ne dérivent pas de la surface des sujets mais d'une source plus enfouie. Comment pourrait-on les expliquer ou les prédire par la rationalité commune ou le savoir mondain ? Seuls ceux qui possèdent une perspicacité et une vision exceptionnelles peuvent en apprécier la profondeur dans les éléments sans son et sans forme »''. Discutant le travail du pinceau de Wang Xizhi (王羲之, 303-361), Zhang note la capacité de Wang à imprégner chaque trait d'intention et à transmettre un sens de transcendance : ''« l'essence sublime de la calligraphie émerge à travers le sans-forme et l'intangible. Le miao est imprévisible. Il provient des manifestations extérieures tout en se cachant dans les intervalles entre les choses »''. Le ''miao'' artistique exige donc autre chose que la maîtrise méticuleuse de la technique : il suppose ce que l'on pourrait appeler, en termes occidentaux, une intuition créatrice, une saisie immédiate qui ne se laisse pas réduire à la procédure. ==== Transformations successives : Song, Yuan, Ming et Qing ==== Il importe ici d'éviter une lecture continuiste : ''miao'' n'a pas exactement la même fonction dans le ''Daodejing'', dans la critique calligraphique des Tang, dans la peinture de paysage des Song ou dans les traités Ming-Qing. Sous les Song (960-1279) et les Yuan (1271-1368), le terme se déplace vers la critique picturale et poétique. Huang Xiufu, dans les ''Yizhou minghua lu'' (益州名畫錄), introduit la catégorie ''miao ge'' (妙格, « classe profonde ») pour désigner les peintures de premier ordre, où la coordination entre le cœur de l'artiste et son habileté se révèle dans la perfection du trait et le maniement de l'encre. Le poète Jiang Kui (姜夔, 1155-1221) identifie quatre aspects du ''gao miao'' (高妙, « haut et subtil ») en poésie : le raisonnement, la signification, l'imagination et la naturalité (''ziran''), terme par lequel le ''miao'' rejoint l'idée d'un advenir sans effort apparent. Su Shi (蘇軾, 1037-1101), poète, peintre et calligraphe, formule la dimension dialectique du ''miao'' : ''« capturer l'essence des choses, c'est comme attraper l'ombre du vent »''. La métaphore est exacte : on ne saisit pas l'ombre, on l'effleure. Le ''miao'' n'est pas dans l'objet mais dans la qualité de la rencontre qui le révèle. Su Shi précise les conditions de cette rencontre : ''« pour créer la beauté poétique, on doit pacifier l'esprit et apaiser l'environnement, car la tranquillité connaît tout mouvement, et le vide accueille tout paysage »''. Guo Xi (郭熙, vers 1020-1090), le grand peintre paysagiste, donne dans le ''Linquan gaozhi'' (林泉高致, « Hautes aspirations des forêts et des sources ») une description précise de l'effet ''miao'' en peinture : ''« dans les peintures, les routes couvertes par les brumes matinales rappellent au spectateur qu'il est un passant matinal ; le soleil couchant à l'horizon fait penser au spectateur de regarder le coucher de soleil ; les habitants des montagnes donnent au spectateur l'impression d'y habiter ; les falaises, les rochers et les sources invitent le spectateur à voyager. Voir des peintures, c'est penser à certaines choses et sentir comme si l'on était littéralement dans la scène. C'est le mystère surprenant [妙] des peintures »''.<ref>Guo Xi, ''Linquan gaozhi'', dans Shen Zicheng (éd.), ''Lidai lunhua mingzhu huibian'', Beijing, Wenwu chubanshe, 1982, p. 68. Cité dans Li Zehou, ''op. cit.'', p. 111.</ref> L'analyse est instructive : le ''miao'' ne tient pas à la fidélité de la représentation, mais à la capacité de la peinture à transporter le spectateur dans la scène. Sous les Ming (1368-1644) et les Qing (1644-1912), le terme se déplace à nouveau, vers une réflexion sur le rapport entre règle et liberté. Xiang Mu (項穆, vers 1550-1600), dans le ''Shufa yayan'' (書法雅言, « Mots élégants sur la calligraphie »), résume bien l'orientation : ''« il y a des méthodes que l'on peut apprendre, mais la subtilité réside dans l'absence d'intention »'' (雖有法可學,妙在無意). On reconnaît l'écho lointain du Cuisinier Ding de Zhuangzi, qui découpait son bœuf sans effort parce qu'il « ne le voyait plus avec les yeux ». Liu Xizai (劉熙載, 1813-1881), théoricien littéraire des Qing, en propose une formulation dialectique à propos de Zhuangzi lui-même : ''« la subtilité [妙] des histoires de Zhuangzi réside dans son usage de la fantaisie pour saisir la vérité, et du réel pour saisir le mystère »'' (莊子之妙,在以幻寫真,以真寫玄). ==== Le mystère (玄, ''xuan'') : explorer la profondeur ==== Le terme ''xuan'' désignait à l'origine la couleur sombre, presque noire, teintée de jaune, du ciel nocturne, parfois nommée ''xuanming'' (玄冥, « mystérieuse et obscure »). Le taoïsme l'a chargé d'une signification cosmologique : parce que le Dao engendre toutes choses dans un état initial de chaos et d'obscurité, ''xuanse'' (玄色, « couleur du mystère ») devient la couleur-mère, et ''xuan'' est associé au yin. Le chapitre 6 du ''Daodejing'' désigne le Dao comme « la porte du mystérieux » (玄牝, ''xuanpin''), racine du Ciel et de la Terre. Le chapitre 1, déjà cité, fait du « mystère du mystère » (玄之又玄) le portail de toutes les subtilités. Yang Xiong (揚雄, 53 avant notre ère - 18 de notre ère) écrit dans le ''Taixuan Jing'' (太玄經, « Classique du Grand Mystère ») : ''« xuan désigne la profondeur cachée et sans forme qui existe parmi toutes les choses »'' (玄者,幽隱無形之妙也). Parce que ''xuan'' désigne la couleur la plus riche, celle qui contient toutes les autres en puissance, il informe directement la pratique de la peinture à l'encre de lavis (水墨, ''shuimo''). Le poète et peintre Wang Wei (王維, 701-761), reconnu comme l'un des fondateurs de cette technique, écrit dans le ''Shanshui Jue'' (山水訣, « Secrets du paysage », attribué) : ''« dans l'art de la peinture, l'encre de lavis est la plus haute. Elle capture naturellement l'essence et crée l'univers »''. Zhang Yanyuan (張彥遠, vers 815-877), dans le ''Lidai Minghua Ji'' (歷代名畫記, « Notes sur les peintures célèbres des dynasties »), formule la doctrine pleinement : ''« les herbes et les arbres fleurissent sans avoir besoin du rouge ; la neige et les nuages flottent sans avoir besoin du blanc ; les montagnes n'ont pas besoin du bleu pour être vertes, ni les phénix des cinq couleurs pour être resplendissants. Lorsque l'encre est utilisée et que les cinq couleurs sont présentes, on dit que c'est réussi. Si l'accent est mis sur les couleurs, l'image de l'objet sera déformée »''.<ref>Zhang Yanyuan, ''Lidai Minghua Ji'', cité dans Li Zehou, ''op. cit.'', p. 110-111, et dans Yolaine Escande, ''Traités chinois de peinture et de calligraphie. Tome I : Les textes fondateurs (des Han aux Sui)'', Paris, Klincksieck, 2003.</ref> L'idée est inattendue et féconde. L'encre noire, déposée sur le papier blanc en valeurs nuancées, suffit à rendre l'univers entier. La couleur, en peinture chinoise classique, n'est pas un manque mais un excès qui obscurcirait la « vraie » apparence des choses. Cette doctrine, conjuguée à l'idée du ''miao'' qui suggère plus qu'il ne montre, a engendré la grande peinture monochrome de paysage des Song et des Yuan, dont les œuvres de Ma Yuan, Xia Gui, Ni Zan (1301-1374) ou Huang Gongwang (1269-1354) restent les sommets. ==== ''Xuanmiao'' comme horizon esthétique ==== Le composé ''xuanmiao'' réunit la profondeur du ''xuan'' et la délicatesse du ''miao''. Il désigne une beauté qui transcende toute forme sensible sans toutefois la dévaluer, qui échappe à toute définition conceptuelle sans pour autant verser dans l'irrationnel, qui réside dans le jeu entre l'être et le non-être, le vide et la plénitude. Comme l'écrit Marcello Ghilardi en commentant la pensée chinoise de l'image, ''« sans forme déterminée, l'image vraie ou grande peut rester libre et donner naissance à différentes perspectives, à plusieurs interprétations. Elle ne s'inscrit dans aucun schéma ni aucune figuration fixe. L'image parfaite ou grande est ainsi un flux, un processus qui laisse advenir quelque chose. Elle est un système de variations, entre apparition et entrave, excluant toute figuration statique »''.<ref>Ghilardi, dans ''The Bloomsbury Research Handbook'', op. cit., chap. 6, p. 111-112.</ref> Le ''xuanmiao'' n'est donc pas un mysticisme : c'est une manière précise de penser le rapport de l'œuvre d'art à ce qui la déborde. L'œuvre vaut moins par ce qu'elle dit que par ce qu'elle laisse à dire, moins par ce qu'elle montre que par ce qu'elle suggère. Cette conception structure encore aujourd'hui une part importante de la sensibilité esthétique chinoise. Elle vaut la peine d'être pensée par-delà sa source : elle propose, dans une langue différente de la nôtre, des questions que notre propre tradition esthétique a parfois oubliées. === La souplesse et le naturel (自然, ''ziran'') === Le terme ''ziran'' (自然) se traduit difficilement par un seul mot français. Composé de ''zi'' (« soi-même ») et ''ran'' (« ainsi », « de cette manière »), il signifie littéralement « ainsi de soi-même », ou « ce qui est de soi-même ainsi ». Les traductions usuelles, « nature », « spontanéité », « naturalité », n'en rendent qu'un aspect. L'idée centrale est celle d'une auto-coïncidence : ce qui est ''ziran'' n'a pas besoin de cause extérieure, n'est pas produit par une intention étrangère à lui-même, advient « tout seul ». Avec le ''wu'' et le ''wuwei'', ''ziran'' constitue l'un des piliers conceptuels de la pensée taoïste, et probablement le plus durablement influent sur la sensibilité esthétique chinoise. ==== Laozi et la loi naturelle du Dao ==== Le ''Daodejing'' inscrit ''ziran'' dans une hiérarchie cosmologique. Le chapitre 25 affirme : ''« l'homme prend la Terre pour modèle ; la Terre prend le Ciel pour modèle ; le Ciel prend le Dao pour modèle ; le Dao prend ''ziran'' pour modèle »'' (人法地,地法天,天法道,道法自然, ''ren fa di, di fa tian, tian fa dao, dao fa ziran''). La formule est délicate. Que le Dao prenne ''ziran'' pour modèle peut sembler étrange si l'on traduit ''ziran'' par « nature », car alors la nature précéderait le Dao. Mais ''ziran'' n'est pas un être : c'est la manière dont le Dao se déploie, sa façon d'être lui-même sans contrainte extérieure. Le Dao ne suit pas de loi qui lui serait imposée du dehors ; il est sa propre loi, et cette loi est ''ziran''. Le chapitre 51 ajoute une nuance importante : ''« l'honneur dont jouit le Dao et l'élévation de son action ne sont pas le résultat d'une ordination : c'est toujours un hommage spontané »''. Le Dao engendre toutes choses sans intention créatrice. ''Ziran'' fait partie du processus par lequel cette génération s'opère. C'est pourquoi le Dao est dit agir sans agir (''wuwei''), produire sans posséder, accomplir sans s'attribuer le mérite. Cette ontologie a des conséquences politiques que Laozi développe largement. Le sage gouverneur n'intervient pas, ou intervient le moins possible : ''« lorsque le succès est atteint et que le peuple dit "c'est naturel", c'est le succès ultime »''. Le chapitre 57 explicite la doctrine du gouvernement par non-intervention : ''« je ne ferai rien dans un but, et le peuple se transformera de lui-même ; je serai attaché à garder le silence, et le peuple deviendra correct de lui-même ; je ne me donnerai aucun trouble, et le peuple deviendra riche de lui-même ; je ne manifesterai aucune ambition, et le peuple aspirera à la simplicité primitive de lui-même »''. À l'inverse, la multiplication des lois et l'agitation administrative engendrent le désordre : ''« plus les lois et les ordres sont rendus visibles, plus il y aura de voleurs et de brigands »''. Cette doctrine politique est inséparable de l'intuition esthétique. Comme l'analyse Li Zehou, le ''ziran'' taoïste s'oppose terme à terme à la conception confucianiste de la beauté, qui repose sur le ''wei'' (為, l'action intentionnelle, l'effort, l'artifice). Pour Xunzi (vers 313-238 avant notre ère), figure confucianiste majeure, « sans l'artifice, la nature ne pourrait s'embellir elle-même » : la beauté requiert le rite, l'éducation, le travail de la forme. Pour Laozi et Zhuangzi, à l'inverse, c'est précisément l'artifice qui dégrade le beau ; la beauté véritable est celle qui n'a besoin de personne.<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 76-77.</ref> ==== Zhuangzi et le naturel non délibéré ==== Zhuangzi pousse l'intuition de ''ziran'' jusqu'à ses conséquences anthropologiques. Là où la tradition pré-Qin dominante voyait dans l'homme un animal raisonnable et volontaire, Zhuangzi propose une vision différente : l'homme, en tant qu'il naît du Dao, possède originellement les qualités du non-désir, du non-savoir, d'une spontanéité non réfléchie. C'est l'éducation sociale qui a recouvert ces qualités d'intelligence, de désirs et d'émotions calculées. Le chapitre ''Mati'' (馬蹄, « Le sabot du cheval ») décrit l'âge primitif : ''« également sans connaissance, ils ne quittaient pas le chemin de leur vertu naturelle ; également libres de désirs, ils étaient dans l'état de simplicité pure. Dans cet état de simplicité pure, la nature du peuple était ce qu'elle devait être »''.<ref>Zhuangzi, chapitre ''Mati'', traduction française adaptée de Burton Watson, ''The Complete Works of Chuang Tzu'', New York, Columbia University Press, 1968, p. 106.</ref> L'idéal éthique qui s'ensuit n'est pas celui d'un retour effectif à l'âge primitif (Zhuangzi ne cultive pas le primitivisme), mais celui d'une recoïncidence intérieure avec ce que le sage taoïste appelle « la simplicité primordiale » (樸素, ''pusu''). Le mot ''pusu'' est composé de deux caractères significatifs : ''pu'' (樸) désigne le bois non sculpté, ''su'' (素) désigne la soie non teinte. La beauté véritable est celle qui n'a pas encore subi le travail de la transformation, ou plutôt celle qui, ayant traversé ce travail, a su revenir à l'état non-travaillé. C'est sur cette base que Zhuangzi peut affirmer la supériorité esthétique de la nature sur l'artifice humain. Le chapitre ''Tiandao'' (天道, « La Voie du Ciel ») le dit : ''« dans leur simplicité primordiale, personne au monde ne peut rivaliser avec eux pour l'excellence »'' (樸素而天下莫能與之爭美). Le sage taoïste, lorsqu'il agit, agit en sorte que son action paraisse n'avoir pas eu lieu, comme un coup de pinceau ne laissant pas voir la main qui l'a tracé. Cette esthétique du non-agir ne propose pas la même image de l'artiste que certaines conceptions modernes européennes. L'artiste ''ziran'' n'est pas un créateur souverain qui impose sa forme à la matière ; il est un médium qui se laisse traverser par la nature des choses. La célèbre anecdote du Cuisinier Ding, dans le chapitre ''Yangshengzhu'' (養生主), en donne l'illustration. Ding débite un bœuf devant son seigneur Wenhui, et sa lame ne rencontre jamais d'obstacle. ''« Ce que j'aime, dit-il, c'est le Dao, ce qui va au-delà de toute technique. Quand j'ai commencé à dépecer des bœufs, je ne voyais que le bœuf entier. Trois ans plus tard, je ne le voyais plus comme un tout. Aujourd'hui, je le rencontre avec mon esprit, je ne le regarde plus avec mes yeux »''.<ref>Zhuangzi, chapitre ''Yangshengzhu'', cité dans Li Zehou, ''op. cit.'', p. 105-106. Voir aussi la discussion de ce passage par Marcello Ghilardi dans ''The Bloomsbury Research Handbook'', op. cit., chapitre 6, p. 107-108.</ref> Le ''ziran'' du Cuisinier Ding n'est pas une spontanéité naïve : il est l'aboutissement d'un long apprentissage. C'est précisément ce que Li Zehou souligne : l'idéal de spontanéité issu de Laozi et Zhuangzi n'exclut pas la maîtrise, il la suppose. Le coup de pinceau qui paraît jaillir sans effort est celui qui a été préparé par dix mille coups d'exercice. La beauté ''ziran'' n'est pas l'absence d'art ; c'est un art parvenu à effacer ses propres traces.<ref>Li Zehou, ''op. cit.'', p. 105-110.</ref> ==== Les Han : du naturel au luxe ==== Sous les Han occidentaux (206 avant notre ère - 9 de notre ère), l'idée taoïsante de naturel a connu une période de faveur officielle. Témoins du désastre causé par les ambitions impériales du Qin (221-207 avant notre ère), les hommes d'État du début des Han ont vu dans la tranquillité et le non-agir une politique de reconstruction. Le ''Huainanzi'' fait de la sérénité et de la simplicité les méthodes adéquates pour nourrir la nature humaine ; il enjoint de se conformer à l'état naturel sans interférer. Cette orientation de retenue fut progressivement concurrencée par l'expansion impériale, le luxe de cour et une culture lettrée de la magnificence. Sous l'empereur Wu de Han (r. 141-87 avant notre ère), la cosmologie corrélative, le ritualisme impérial, l'administration légiste et le confucianisme institutionnel coexistent avec des motifs taoïsants, sans qu'aucun ne s'impose exclusivement. Les ''fu'' (賦, longs poèmes en prose rythmée) du I^er siècle, par exemple le ''Shanglin fu'' (上林賦, « Ode à la forêt supérieure ») de Sima Xiangru (vers 179-117 avant notre ère) ou le ''Xidu fu'' (西都賦, « Ode à la capitale occidentale ») de Ban Gu, déploient une rhétorique de l'abondance et de l'ostentation : les marchés, les palais, les parcs de chasse y sont décrits avec une minutie qui célèbre la magnificence impériale. Cette tension entre naturel et magnificence prépare, à la chute des Han au IIe siècle, le retour aux textes de Laozi et de Zhuangzi et l'élaboration du ''Xuanxue'' sous les Wei-Jin. ==== Wei-Jin : transcender les normes, suivre la voie naturelle ==== Sous les Wei et les Jin (220-420), le ''Xuanxue'' (玄學) opère une revalorisation systématique du naturel. Wang Bi expose la doctrine en trois propositions, dans son commentaire au ''Daodejing'' : ''« le Ciel et la Terre suivent la voie naturelle sans agir, et toutes les choses se gouvernent elles-mêmes »'' ; ''« les signes de la nature peuvent être vus mais non saisis, et sa signification peut être perçue mais non capturée »'' ; ''« ceux qui suivent la loi de la nature se conforment au carré lorsque les choses doivent être carrées, et à la rondeur lorsque les choses doivent être rondes »''.<ref>Wang Bi, ''Annotations au Daodejing'', chapitres 5, 17 et 25, édition Lou Yulie, Beijing, Zhonghua shuju, 1980, p. 14, 42, 63. Cité dans Lin, art. cit., p. 139.</ref> La beauté de la nature, pour Wang Bi, tient à ceci qu'elle peut être influencée mais non manipulée, comprise mais non saisie. Le sage taoïste suit la pente des choses, il ne la force pas. Cette doctrine, appliquée à l'éthique politique, débouche sur une critique des rituels confucianistes : Wang Bi y voit des contraintes artificielles imposées à une nature humaine qui n'en a pas besoin. Ruan Ji (210-263) et Ji Kang (223-262) durcissent cette critique. Ruan Ji écrit que ''« la nature a donné naissance au Ciel et à la Terre, qui ont donné naissance à toutes les choses »'' ; il oppose à l'hypocrisie des rituels confucianistes l'idée d'une vie conforme au Dao. Dans la ''Daren Xiansheng Zhuan'' (大人先生傳, « Légende de Monsieur la Grande Personne »), il professe sa hostilité aux conventions sociales et fait l'éloge d'une existence libre, mobile, échappant aux contraintes du protocole. Ji Kang, dans ''Shi Si Lun'' (釋私論, « Discutant de l'égoïsme »), affirme : ''« ceux qu'on appelle individus nobles sont ceux dont les cœurs ne sont pas perturbés par les jugements du bien et du mal, et dont les actions ne vont pas à l'encontre du Dao [...] Si l'on agit selon la nature, il n'y aura aucune déviation du Dao. En embrassant l'unité sans perturbation, il n'y aura ni bien ni mal. Ainsi, on agit selon les conditions de la beauté ultime »''. Ce qu'écrit Ji Kang n'est pas un amoralisme : c'est l'idée qu'au-delà des dichotomies imposées par le rituel social, une coïncidence avec la nature permet d'agir justement sans avoir à délibérer du juste. Cette éthique a un revers tragique. Ji Kang sera exécuté en 262, et l'élite culturelle des Jin se réfugiera dans une « conversation pure » (''qingtan'') souvent décrite comme évasive ou décadente.<ref>Sur le contexte politique et culturel des Wei-Jin, voir Zong-qi Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 2-4. Sur la portée philosophique du ''Xuanxue'', voir Shuen-fu Lin, « A Good Place Need Not Be a Nowhere », ''ibid.'', p. 123-167.</ref> Mais cette retraite intellectuelle a aussi une fécondité esthétique considérable : la poésie de paysage, la peinture à l'encre, l'art du jardin, la théorie calligraphique se développent dans ce milieu. ==== Dynasties du Sud : le lotus de l'eau claire ==== Sous les dynasties du Sud (420-589), deux tendances esthétiques coexistent et parfois s'affrontent. D'un côté, une littérature ornée fleurit : poésie de paysage très travaillée, poésie de cour, prose appariée aux rythmes complexes. De l'autre, dans la lignée de Laozi et Zhuangzi, une poésie de la simplicité et du retrait prend forme, qui célèbre la tranquillité, l'effacement, la naturalité. Liu Xie (劉勰, vers 465-522), dans le ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit de la littérature et la Sculpture du dragon''), formule une synthèse d'envergure. Le premier chapitre, ''Yuandao'' (原道, « De l'origine, du Dao »), pose une équivalence subtile : le monde dans sa forme merveilleuse est le ''wen'' du Dao (道之文, ''dao zhi wen'') ; à son tour, le ''wen'' littéraire est la manifestation de l'esprit humain (心, ''xin''). Comme l'explicite Marcello Ghilardi, Liu Xie joue sur la polysémie du caractère ''wen'', qui signifie à la fois « écriture, littérature », « motif, ornement, pattern » et « culture, civilisation ».<ref>Marcello Ghilardi, dans ''The Bloomsbury Research Handbook'', op. cit., chap. 6, p. 105.</ref> Le travail littéraire ne s'oppose pas à la nature : il en est le prolongement humain, à condition de demeurer fidèle à l'ordre que le Dao manifeste dans le cosmos. Liu Xie tire de cette doctrine un précepte normatif : la création littéraire doit suivre un processus naturel d'expression des sentiments, sans embellissement excessif ni prétention. Sa critique vise les excès de l'ornementation contemporaine, sans pour autant rejeter le travail de la forme. Zhong Rong (鍾嶸, vers 469-518), dans la préface aux ''Shipin'' (詩品, ''Jugements poétiques''), va plus loin. Il s'en prend explicitement aux inventeurs de la poésie en vers régulés (Shen Yue, 441-513, et son école), dont les contraintes formelles, à ses yeux, étouffent la beauté véritable. Sa proposition est claire : ''« l'écriture littéraire doit être propice à la récitation et ne doit pas être contrainte excessivement. Il suffit de la faire couler en douceur et harmonieusement »''. Le contraste entre la beauté naturelle et la beauté ornementée a trouvé son image dans une opposition devenue proverbiale. Le critique Tang Huixiu, contemporain des dynasties du Sud, comparait les poèmes de Xie Lingyun (謝靈運, 385-433) à un « lotus émergeant de l'eau » (出水芙蓉, ''chushui furong'') et ceux de Yan Yanzhi (顏延之, 386-456) à de l'« or finement incrusté » (錯彩鏤金, ''cuocai loujin''). Bao Zhao (鮑照, vers 414-466) reprend la comparaison, à l'avantage du lotus : ''« les poèmes pentasyllabiques de Xie Lingyun sont comme un lotus fraîchement éclos, naturellement charmant ; les poèmes de Yan Yanzhi sont comme une beauté brodée remplie de motifs incrustés »''. Le philosophe et historien de l'esthétique Zong Baihua (1897-1986), commentant ce passage, y voit l'attestation d'une transition décisive dans la sensibilité chinoise : l'idéal de la « beauté ornée » cède le pas à celui de la « beauté naturelle ». L'expression « lotus fraîchement éclos » devient l'emblème d'une catégorie esthétique supérieure à celle de l'« or incrusté ».<ref>Zong Baihua, ''Meixue Sanbu'' (美學散步, « Promenades en esthétique »), Shanghai, Shanghai renmin chubanshe, 1981, p. 29. La discussion est reprise dans Li Zehou, ''op. cit.'', p. 96-98.</ref> ==== Tang et Song : la beauté naturelle au-dessus de l'embellissement ==== Sous les Tang (618-907) et les Song (960-1279), la doctrine de la beauté naturelle devient un lieu commun de la critique. Les théoriciens admettent que l'art est un produit humain, mais soutiennent qu'il doit dissimuler sa propre artificialité, s'aligner sur le mode d'opération de la nature. Le grand poète Li Bai (李白, 701-762) résume l'idéal en deux vers : ''« d'une eau claire émerge le lotus, qui est naturellement dépourvu d'embellissement »'' (清水出芙蓉,天然去雕飾). Han Yu (韓愈, 768-824), dans le ''Shigu Ge'' (石鼓歌, « Chant des tambours de pierre »), exprime un sentiment analogue : ''« les trésors précieux ne nécessitent aucun embellissement ; leur nature divine refuse la cultivation artificielle »''. Pei Du (765-839), dans sa lettre à Li Ao, écrit : ''« la vraie distinction dans la littérature réside dans l'élévation de son esprit et la profondeur de ses pensées, non dans la complexité de sa formulation ou sa rime »''. Sikong Tu (司空圖, 837-908), dans ses ''Vingt-quatre catégories de poésie'' (二十四詩品, ''Ershisi Shipin''), formule le précepte qui résume toute l'époque : ''« la subtilité dérive de la nature »'' (妙造自然, ''miao zao ziran''). L'évolution la plus nette se produit dans la critique picturale. Zhang Yanyuan, dans le ''Lidai Minghua Ji'', établit une hiérarchie qui place la naturalité (''ziran'') au-dessus de la divinité (''shen'') et de la subtilité (''miao''). C'est un renversement notable : la catégorie suprême devient celle de l'œuvre qui paraît n'avoir pas été faite, qui s'est dépouillée de toute trace d'effort. Sous les Song, la nouvelle catégorie critique de ''yi pin'' (逸品, « œuvre d'aisance ») devient le sommet de l'évaluation picturale. Comme l'expose Li Zehou : ''« le "yi pin" est, dans la peinture, le plus difficile à atteindre. En défi des règles conventionnelles de composition, dédaignant le raffinement de la couleur et du trait, avec des coups simples qui saisissent la forme, il atteint le naturel, l'inimitable et l'inattendu »''.<ref>Li Zehou, ''op. cit.'', p. 94. La catégorie ''yi pin'' avait été introduite plus tôt par Huang Xiufu, mais c'est sous les Song qu'elle acquiert son rang supérieur. Sur l'évolution de cette catégorie, voir Yolaine Escande, « ''Yipin'' as an Aesthetic Category: From Calligraphy to Painting in the Chinese Art Theory », dans Tsunemichi Kambayashi et al. (éd.), ''Tradition and Transformation in Aesthetics of East Asian Calligraphy'', Tokyo, Sangensha, 2016, p. 112-143.</ref> Un autre critique exprime la même idée : ''« bien que l'œuvre divine soit considérée comme la plus haute réalisation pour un peintre, certains placent l'œuvre d'aisance au-dessus d'elle, disant que c'est au prix du naturel que la divinité est atteinte »''.<ref>Dong Qichang, ''Hua Chan Shi Sui Bi'', cité dans Li Zehou, ''op. cit.'', p. 94.</ref> ==== Ming et Qing : la beauté de la nature humaine ==== Sous les Ming (1368-1644) et les Qing (1644-1912), la doctrine du ''ziran'' connaît une inflexion nouvelle. L'orthodoxie néo-confucianiste, dominante depuis Zhu Xi (1130-1200), avait subordonné les émotions et les désirs naturels au Principe céleste (天理, ''tianli''). Une rébellion intellectuelle, à la fin des Ming, conteste cette subordination et revalorise les passions humaines comme part intégrante de la nature. La figure centrale de cette rébellion est Li Zhi (李贄, 1527-1602), penseur hétérodoxe et hardi. Sa doctrine du « cœur d'enfant » (童心, ''tongxin'') affirme la dignité du sentiment spontané, non encore corrompu par l'éducation rituelle. Li Zhi va jusqu'à défendre ouvertement l'« égoïsme » (私, ''si'') et le « profit » (利, ''li'') comme expressions légitimes de la nature humaine : ''« l'égoïsme est le cœur de l'homme. Une personne doit avoir de l'égoïsme pour que son esprit devienne manifeste. C'est comme si sans égoïsme il ne pouvait y avoir d'esprit »''.<ref>Li Zhi, ''Fenshu'' (焚書, « Livre à brûler »), juan 3, cité dans Li Zehou, ''op. cit.'', p. 199-200.</ref> L'enjeu esthétique est considérable. Si la nature humaine inclut légitimement les désirs, les passions, les sentiments sensuels, alors la littérature et l'art peuvent les exprimer sans honte. Le théâtre de Tang Xianzu (湯顯祖, 1550-1616), les romans de mœurs comme le ''Jin Ping Mei'', la peinture iconoclaste de Xu Wei (徐渭, 1521-1593) et plus tard de Shitao (石濤, 1642-1707) ou de Bada Shanren (1626-1705), s'inscrivent dans cette inflexion. Le ''ziran'' n'est plus seulement le naturel cosmique ou la spontanéité du sage taoïste : c'est aussi la vérité du cœur humain, dans toute sa complexité, ses contradictions, ses excès. Yuan Mei (袁枚, 1716-1798), critique et poète des Qing, formule cette doctrine sous une forme plus modérée mais non moins ferme. Il rejette l'orthodoxie de la « douceur et de la sincérité » (溫柔敦厚, ''wenrou dunhou'') qui demandait à la poésie d'être édifiante : ''« la "douceur et la sincérité" ne sont qu'une extrémité du spectre poétique. Il n'est pas nécessaire de la rechercher avant tout [...] J'accepte le commentaire de Confucius selon lequel la poésie doit refléter les sentiments des gens du peuple. Ce que je n'accepte pas, c'est l'idée qu'elle doit être douce et sincère »''.<ref>Yuan Mei, cité dans Li Zehou, ''op. cit.'', p. 204-205.</ref> ==== ''Ziran'' comme idéal esthétique ==== Au terme de ce parcours, ''ziran'' apparaît moins comme un concept que comme une orientation, une polarité régulatrice de l'expérience esthétique chinoise. Plusieurs traits méritent d'être soulignés. Le ''ziran'' n'est pas l'anti-art. Il ne s'agit pas, pour le peintre ou le poète, de renoncer à toute discipline pour produire des œuvres spontanées au sens naïf du terme. La spontanéité ''ziran'' suppose au contraire un long travail de l'art sur lui-même, par lequel il en vient à effacer ses propres traces. Le Cuisinier Ding apprend pendant trois ans avant de « ne plus voir » le bœuf entier. Le ''ziran'' ne s'oppose pas frontalement à la culture. Il y a, dans la tradition chinoise, une dialectique constante entre ''ziran'' et ''wen'' (文, « culture, civilisation, motif »), entre le donné naturel et l'élaboration humaine. L'idéal n'est pas l'un sans l'autre, mais un certain équilibre où la culture, parvenue à maturité, recoïncide avec la nature qu'elle avait d'abord transformée. C'est ce que Liu Xie disait à sa manière dans le ''Wenxin Diaolong'' : le ''wen'' littéraire est, ou doit être, le prolongement humain du ''wen'' cosmique. Le ''ziran'' privilégie la souplesse sur la rigidité. C'est le second sens du titre que nous avons donné à cette section. Le ''Daodejing'' fait constamment l'éloge de l'eau, qui ne combat pas mais finit par creuser la pierre, du nourrisson dont les os sont mous mais l'étreinte ferme, du rameau souple qui ploie et ne se brise pas. Cette esthétique de la souplesse informe la calligraphie (où le coup de pinceau doit garder sa fluidité), la peinture (où les traits doivent rester vivants), la poésie (où les vers doivent éviter la raideur métrique). Le ''ziran'' ouvre enfin un horizon où l'opposition entre sujet et objet, entre intérieur et extérieur, perd de son tranchant. L'œuvre vraiment ''ziran'' n'est pas exactement produite par un sujet souverain : elle advient à la rencontre du peintre et du paysage, du poète et de la chose, du calligraphe et du pinceau. Cette manière de penser la création se distingue de certaines figures européennes modernes du génie souverain ; étant entendu que le romantisme européen connaît aussi, à sa façon, des modèles de l'inspiration, de la passivité créatrice et de l'accord avec la nature, parfois proches à certains égards. Cette dimension demeure l'un des apports les plus précieux des courants taoïsants à la réflexion esthétique générale. == Le bouddhisme et l'esthétique du vide == Le bouddhisme arrive en Chine depuis l'Inde au tournant de l'ère commune et se sinise progressivement par un long travail de traduction, de syncrétisme et d'élaboration. Trois étapes peuvent en résumer le mouvement : du I{{er}} au IV{{e}} siècle, l'effort de traduction des ''sūtras'' indiens et la mise au point d'une terminologie chinoise empruntée pour partie au vocabulaire taoïste ; du V{{e}} au VI{{e}} siècle, la propagation rapide de la doctrine et son intrication avec le ''Xuanxue'' des Wei-Jin ; du VII{{e}} au X{{e}} siècle, l'efflorescence des écoles spécifiquement chinoises, parmi lesquelles le Tiantai (天台), le Huayan (華嚴), le Sanlun (三論) et surtout le Chan (禪), qui devait exercer une influence considérable sur la poésie et la peinture lettrées.<ref>Sur cette périodisation, voir Wang Keping, « A General Introduction to Chinese Aesthetics », dans Marcello Ghilardi et Chakravarthi Ram-Prasad (dir.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', London, Bloomsbury, 2017, chap. 1, section « The Pursuit of Chan Buddhism ». Pour une présentation détaillée en français, voir Anne Cheng, ''Histoire de la pensée chinoise'', Paris, Seuil, 1997 (rééd. « Points Essais », 2002), chapitres 16 à 19.</ref> Présenter le bouddhisme comme un bloc homogène serait inexact : les positions doctrinales et esthétiques varient sensiblement d'une école à l'autre, et l'on doit distinguer la littérature de la ''Prajñāpāramitā'', l'école Madhyamaka, le bouddhisme dévotionnel de la Terre pure et la tradition Chan. Les pages qui suivent se concentrent sur deux articulations majeures : la doctrine selon laquelle « la forme est vide » (色即是空), héritée de la littérature de la Perfection de la Sagesse et reformulée en Chine par Sengzhao, puis l'esthétique du Chan, dont la notion de « vide subtil » (空靈, ''kong ling'') devait durablement nourrir la poésie et la peinture lettrées. === La forme est vide (色即是空, ''se ji shi kong'') === ==== La Perfection de la Sagesse et le ''Sūtra du Cœur'' ==== La formule « la forme est vide, le vide est forme » appartient à la vaste littérature de la ''Prajñāpāramitā'' (般若波羅蜜多, « Perfection de la Sagesse »), dont la composition s'étend, en Inde, du I{{er}} siècle avant notre ère au IV{{e}} siècle de notre ère. Le ''Sūtra du Cœur'' (般若波羅蜜多心經, ''Prajñāpāramitā-hṛdaya-sūtra''), bref texte d'une page environ, en condense les thèses principales et devient, en Asie orientale, l'un des textes bouddhiques les plus récités. La question de l'origine indienne ou chinoise du ''Sūtra du Cœur'' demeure discutée : Jan Nattier a défendu l'hypothèse selon laquelle le texte aurait été compilé en Chine, à partir de passages de la grande ''Prajñāpāramitā'', avant d'être retraduit en sanskrit.<ref>Jan Nattier, « The Heart Sutra: A Chinese Apocryphal Text? », ''Journal of the International Association of Buddhist Studies'' 15, no. 2 (1992), p. 153-223. L'hypothèse a suscité un débat important qui demeure ouvert.</ref> Quel que soit le verdict sur ce point, le bodhisattva Avalokiteśvara y déclare à Śāriputra : « La forme est vide, le vide est forme. La forme n'est pas différente du vide, le vide n'est pas différent de la forme » (色即是空,空即是色,色不異空,空不異色).<ref>Pour le texte sanskrit et chinois ainsi qu'une analyse philologique, voir Donald S. Lopez Jr., ''The Heart Sūtra Explained: Indian and Tibetan Commentaries'', Albany, State University of New York Press, 1988. Une traduction française fait autorité : Jean-Noël Robert (trad.), ''Sūtra du Cœur'' (en appendice à diverses éditions).</ref> La formule s'applique non seulement à la « forme » (色, ''rūpa''), mais aux cinq agrégats (五蘊, ''pañca-skandha'') qui composent l'expérience : forme, sensations (受, ''vedanā''), perceptions (想, ''saṃjñā''), formations volitionnelles (行, ''saṃskāra'') et conscience (識, ''vijñāna''). Toute composante de l'existence est dite « vide » au sens où elle ne possède pas d'existence propre, indépendante, fixe. ==== Nāgārjuna et la coproduction conditionnée ==== Le concept de vide (空, ''śūnyatā'') reçoit son élaboration philosophique la plus poussée chez Nāgārjuna (龍樹, vers 150-250 de notre ère), figure tutélaire de l'école Madhyamaka (中觀派, « école de la Voie médiane »). Dans les ''Mūlamadhyamakakārikā'' (中論, « Stances fondamentales sur la Voie médiane »), Nāgārjuna identifie le vide à la coproduction conditionnée (緣起, ''pratītya-samutpāda'') : un phénomène est dit vide non parce qu'il n'existe pas, mais parce qu'il n'existe qu'en dépendance d'autres phénomènes. La stance 18 du chapitre 24, devenue canonique, résume la doctrine : « Ce qui surgit en coproduction conditionnée, nous le qualifions de vide. Cette désignation est tributaire ; elle est elle-même la voie médiane » (眾因緣生法,我說即是空,亦為是假名,亦是中道義).<ref>Nāgārjuna, ''Mūlamadhyamakakārikā'', chap. 24, stance 18. Pour la traduction et le commentaire, voir Jay L. Garfield (trad.), ''The Fundamental Wisdom of the Middle Way: Nāgārjuna's'' Mūlamadhyamakakārikā, New York, Oxford University Press, 1995. Voir aussi, en français, Guy Bugault (trad.), Nāgārjuna, ''Stances du milieu par excellence'', Paris, Gallimard, « Connaissance de l'Orient », 2002.</ref> Le vide ainsi compris n'est ni une substance, ni un néant. Il est une caractéristique formelle de tout phénomène : être en dépendance, ne pas posséder d'essence propre. La Voie médiane consiste à éviter les deux extrêmes du substantialisme et du nihilisme. Cette formulation indienne, qui paraît à première lecture purement métaphysique, devait recevoir en Chine des reformulations où le vocabulaire de Laozi et de Zhuangzi joua un rôle considérable. ==== Sengzhao et l'irréalité du vide ==== L'œuvre de Sengzhao (僧肇, 374-414) marque la première grande appropriation chinoise de la pensée Madhyamaka. Disciple de Kumārajīva (鳩摩羅什, 344-413), grand traducteur d'origine kuchéenne arrivé à Chang'an en 401, Sengzhao a participé à la traduction des principaux traités de Nāgārjuna et d'Āryadeva en chinois. Ses propres écrits, réunis sous le titre ''Zhao Lun'' (肇論, « Traités de Zhao »), comprennent quatre essais aujourd'hui distingués : le ''Wu buqian lun'' (物不遷論, « Traité de l'immutabilité des choses »), le ''Bu zhenkong lun'' (不真空論, « Traité de l'irréalité du vide »), le ''Bore wuzhi lun'' (般若無知論, « Traité sur l'absence de connaissance de la ''prajñā'' ») et le ''Niepan wuming lun'' (涅槃無名論, « Traité sur l'absence de nom du nirvāṇa »).<ref>Pour une présentation d'ensemble du ''Zhao Lun'' et de ses quatre traités, voir Hans-Rudolf Kantor, « Zhao Lun », ''Encyclopedia of Buddhism'', Detroit, Macmillan Reference USA, 2004 ; et Richard H. Robinson, ''Early Mādhyamika in India and China'', Madison, University of Wisconsin Press, 1967, p. 123-155. Sur Sengzhao spécifiquement, voir Chien-hsing Ho, « The Nonduality of Motion and Rest: Sengzhao on the Change of Things », ''Dao: A Journal of Comparative Philosophy'' 17 (2018).</ref> La notice antérieure de l'article qui regroupait sous le titre « Wubuqian kong lun » deux traités distincts résultait d'une confusion : ce titre n'existe pas dans le canon. Le ''Bu zhenkong lun'' développe la position centrale de Sengzhao : les choses ne sont ni véritablement existantes ni purement inexistantes, et le vide n'est pas un néant qui s'opposerait à l'existence. Sengzhao critique trois interprétations défectueuses qui circulaient à son époque, regroupées sous le nom des « trois sortes de vide » (三家義) : l'interprétation qui réduit le vide à l'absence des objets dans un esprit pacifié, celle qui l'identifie à la matérialité, celle qui le pose comme néant. Contre ces lectures, Sengzhao soutient que le vide désigne le mode même selon lequel les choses sont : irréelles en tant qu'on les considère comme existant en soi, irréelles également en tant qu'on les nie purement et simplement. Le vide est l'envers exact de l'apparition conditionnée. Ses formulations frappantes (« les dix mille choses sont vides dès le commencement », 萬物自虛) ouvrent la voie à une terminologie spécifiquement chinoise du vide.<ref>Pour une discussion philosophique récente, voir Eric S. Nelson, ''Daoism and Environmental Philosophy: Nourishing Life'', London, Routledge, 2021, chap. sur Sengzhao ; et la synthèse de Chien-hsing Ho, « Emptiness as Subject-Object Unity: Sengzhao on the Way Things Truly Are », dans Sandra A. Wawrytko et Youru Wang (dir.), ''Dao Companion to Chinese Buddhist Philosophy'', Dordrecht, Springer, 2018, p. 167-186.</ref> Sengzhao opère cette élaboration en empruntant largement au vocabulaire du Laozi et du Zhuangzi. Le vide est dit ''xu'' (虛), ''wu'' (無), ''zikong'' (自空, « auto-vide »), termes qui circulaient déjà dans la pensée taoïste et le ''Xuanxue''. Cette continuité lexicale n'est pas une concession syncrétique : elle traduit le fait que les commentateurs chinois disposaient, avant l'arrivée du bouddhisme, d'un appareil conceptuel pour penser le vide comme matrice plutôt que comme néant. Sengzhao réoriente ce matériau dans le cadre d'une analyse Madhyamaka rigoureuse, et son écriture, élégante et paradoxale, en fait l'un des grands prosateurs philosophiques de la tradition chinoise. ==== Du vide doctrinal au vide esthétique ==== La doctrine du vide n'est pas, en elle-même, une théorie esthétique. Sa réception en Chine produit néanmoins un déplacement notable : la notion de ''kong'' (空), qui désignait initialement le vide ontologique des phénomènes, devient progressivement, à partir des Six Dynasties, une catégorie de la perception sensible et de la composition picturale. Ce déplacement n'est pas immédiat ; il suppose l'élaboration d'un milieu lettré bouddhiste laïc, des écoles syncrétiques et un long travail de la poésie et de la peinture. Sous les Six Dynasties, le bouddhisme laïc se diffuse dans l'élite lettrée. Dans certains milieux, la prise des cinq préceptes et l'idéal du laïc Vimalakīrti, modèle du ''jushi'' (居士, ''upāsaka''), deviennent des marques de distinction religieuse et culturelle.<ref>Sur le bouddhisme laïc dans les Six Dynasties, voir François Martin, « Literary Games and Religious Practice at the End of the Six Dynasties: The ''Baguanzhai'' Poems by Xiao Gang and His Followers », dans Zong-qi Cai (éd.), ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawai'i Press, 2004, p. 222-247.</ref> Shen Yue (沈約, 441-513), à la fois prolifique écrivain bouddhiste et tenant du « nouveau mouvement » poétique, ou Xiao Gang (蕭綱, 503-551), prince patron de monastères et auteur prolifique de poésie courtoise, illustrent la coexistence, parfois tendue, d'une religion du détachement et d'une culture de la cour sensible aux plaisirs. C'est dans ce milieu que des poètes comme Zhi Dun (支遁, 314-366), Xie Lingyun (謝靈運, 385-433) et Wang Wei (王維, 701-761) explorent une poésie où le « vide » et la « tranquillité » deviennent des qualités sensibles autant que des prédicats métaphysiques.<ref>Pour la trajectoire poétique de ces auteurs et le glissement du vide ontologique au vide esthétique, voir Xia Kejun, « Nature as Not-yet-existing Beauty: Infra-thin Poetic Art of Enchorial-topia », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 7 ; et Li Zehou, ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawai'i Press, 2010, chap. 5, « Metaphysical Pursuits ».</ref> Marcello Ghilardi note que la peinture chinoise classique élabore une véritable interaction entre ''wu'' (無, absence, non-être, vide) et ''you'' (有, présence, être, plein), qui doit autant au Laozi qu'aux développements bouddhistes. Le critère lettré des « quatre qualités » de la pierre du lac Tai (瘦, ''shou'', minceur ; 皺, ''zhou'', texture ridée ; 漏, ''lou'', canaux ; 透, ''tou'', perforation) résume la sensibilité d'époque Tang à la pierre comme jeu de plein et de vide. Ji Cheng cite à ce propos un vers du poète et peintre bouddhiste Wang Wei : « le déploiement des montagnes se tient entre l'être et le non-être ».<ref>Sur la pierre du lac Tai et les quatre critères ''shou-zhou-lou-tou'', voir Graham Parkes, « The Role of Rock in Chinese Aesthetics », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 8. Le vers de Wang Wei (山色有無中) est commenté dans Ghilardi, ''ibid.'', chap. 6, p. 110.</ref> Le couplet, repris par d'innombrables critiques, condense la position : la beauté apparaît à la lisière entre quelque chose et rien, dans l'oscillation entre détermination et indétermination. === Rhétorique monastique et critique de l'attachement === Le bouddhisme indien, ainsi que les écoles monastiques qui s'en réclament, développe une littérature spirituelle où la dépréciation de la beauté sensible joue un rôle pratique : il s'agit, pour le moine engagé dans la voie de la libération, de défaire l'attachement aux objets désirables, dont le corps des autres et le sien propre. Cette littérature comprend notamment la pratique de la « contemplation de l'impureté » (不淨觀, ''aśubha-bhāvanā''), exposée dans l'''Abhidharmakośa'' de Vasubandhu et dans le ''Da zhidu lun'' (大智度論, ''Mahāprajñāpāramitopadeśa'', traité attribué à Nāgārjuna et traduit par Kumārajīva), qui invite à observer le corps comme composé d'éléments répugnants ou comme passant par les étapes de la décomposition cadavérique. La portée de ces textes mérite d'être bien située. Il s'agit de méditations-antidotes destinées à un public monastique, conçues comme contrepoids ascétique à la pulsion sensible. Elles ne constituent pas une théorie esthétique bouddhiste générale et l'on ne peut, sans grave anachronisme, en tirer une position du « bouddhisme » sur la beauté. La rhétorique anti-féminine que l'on trouve chez certains auteurs monastiques, dont Yongjia Xuanjue (永嘉玄覺, 665-713), appartient à ce registre d'exhortation ascétique adressée aux moines. Présentée hors contexte, comme caractéristique de l'esthétique bouddhiste, elle donne une image fausse de cette tradition, qui comprend également des ''sūtras'' tels que le ''Saddharmapuṇḍarīka-sūtra'' (法華經, « Sūtra du Lotus ») où l'éveil est explicitement accessible à toutes et à tous, y compris à la fille du roi-nāga qui atteint l'éveil dans un de ses chapitres les plus commentés, même si cet épisode demeure marqué par les représentations genrées de son époque, puisqu'il passe par une transformation masculine préalable. Ce qui passe de cette littérature monastique dans l'esthétique chinoise lettrée n'est pas la dépréciation de la beauté féminine, mais une conscience aiguë de l'impermanence (無常, ''anitya'') et de la souffrance liée à l'attachement. Cette conscience traverse la poésie des Tang et des Song, et trouve une expression non répulsive dans le motif de la fleur qui tombe, du miroir vide, du nuage qui se dissipe. Les similes du ''Vimalakīrti-nirdeśa-sūtra'' (維摩詰所說經, « Sūtra de l'enseignement de Vimalakīrti ») sur le corps comme « amas d'écume », « bulle d'eau », « mirage », « bananier sans cœur », « rêve », « écho », « ombre », « nuage », « éclair »<ref>Pour la traduction française, voir Patrick Carré (trad.), ''Soûtra de la Liberté inconcevable. Les enseignements de Vimalakîrti'', Paris, Fayard, 2000. La liste de similes est au chapitre 2.</ref> ont nourri, au-delà du strict cadre monastique, une rhétorique poétique de la transience qui se confond difficilement avec une condamnation de l'art. === L'école Chan et l'esthétique du vide === L'école Chan (禪宗, ''Chan zong''), connue en Asie orientale sous ses formes coréenne (''Sŏn''), japonaise (''Zen'') et vietnamienne (''Thiền''), constitue l'aboutissement chinois le plus original de la sinisation du bouddhisme. Sa formation et sa légitimation se jouent du VI{{e}} au VIII{{e}} siècle ; à partir de la fin des Tang et surtout sous les Song, elle devient l'un des interlocuteurs bouddhiques majeurs de la culture lettrée et marque durablement la peinture, la poésie, la calligraphie et l'art des jardins. ==== Origines : tradition légendaire et formation historique ==== La tradition Chan se réclame d'une transmission ininterrompue depuis le Bouddha Śākyamuni. Selon le récit hagiographique, le Bouddha aurait, lors d'un sermon sur le mont des Vautours, brandi une fleur sans rien dire ; seul Mahākāśyapa aurait souri en comprenant, recevant ainsi du Bouddha la transmission directe, sans paroles, de « l'œil du trésor de la vraie Loi » (正法眼藏, ''zheng fa yan zang''). De Mahākāśyapa, la transmission se serait poursuivie jusqu'à un vingt-huitième patriarche indien, Bodhidharma (菩提達摩, dates traditionnelles vers 470-543), qui aurait apporté l'enseignement en Chine vers 520 et serait devenu le premier patriarche de la lignée chinoise.<ref>Anne Cheng, ''Histoire de la pensée chinoise'', op. cit., chapitre 18, en particulier p. 423 et suivantes.</ref> Les recherches historiques contemporaines ont fortement nuancé ce récit. La figure de Bodhidharma reste largement légendaire ; sa biographie est reconstruite tardivement, principalement à partir de matériaux des VIII{{e}} et IX{{e}} siècles, et la lignée des vingt-huit patriarches indiens apparaît comme une construction rétrospective destinée à fonder l'autorité du Chan dans une généalogie ininterrompue depuis le Bouddha.<ref>Pour une mise au point historiographique, voir John R. McRae, ''Seeing through Zen: Encounter, Transformation, and Genealogy in Chinese Chan Buddhism'', Berkeley, University of California Press, 2003. McRae propose notamment le principe : « Lineage assertions are as wrong as they are strong » (les assertions de filiation sont aussi fausses qu'elles sont fortes), qui invite à lire ces récits comme des constructions identitaires plus que comme des chroniques historiques.</ref> Les véritables prémices d'une pensée Chan se trouvent au IV{{e}} siècle, en amont de la lignée légendaire, chez des auteurs comme Daosheng et chez Sengzhao lui-même, dont les écrits préparent le terrain conceptuel à la doctrine de l'éveil subit. ==== Daosheng et l'illumination subite ==== Daosheng (道生, vers 355-434), disciple de Huiyuan (慧遠, 334-416), est généralement reconnu comme le premier théoricien chinois de l'éveil subit (頓悟, ''dunwu''). Sa thèse découle d'un raisonnement précis : si le principe (理, ''li'') est indivisible, et si la nature de Bouddha (佛性, ''foxing'') est présente en chaque être, alors l'éveil ne peut être divisible en étapes graduelles. L'éveil est total ou il n'est pas. Daosheng soutient également la thèse, audacieuse pour son époque, que les ''icchantika'' (一闡提, êtres réputés irrémédiablement perdus dans certaines lectures) eux-mêmes possèdent la nature de Bouddha.<ref>Sur Daosheng et la doctrine de l'éveil subit, voir Walter Liebenthal, « The World Conception of Chu Tao-sheng », ''Monumenta Nipponica'' 12, no. 1-2 (1956) ; et Whalen Lai, « The Mahāparinirvāṇa-sūtra and Its Earliest Interpreters in China: Two Prefaces by Tao-lang and Tao-sheng », ''Journal of the American Oriental Society'' 102 (1982). Pour une synthèse en français, voir Cheng, ''Histoire de la pensée chinoise'', op. cit., p. 384-385.</ref> Cette thèse, d'abord rejetée, fut confirmée par la traduction ultérieure d'une version complète du ''Mahāparinirvāṇa-sūtra'' (大般涅槃經) et conféra à Daosheng une autorité posthume considérable. Daosheng emprunte au Zhuangzi la métaphore du piège : une fois le poisson pris, on peut oublier la nasse ; une fois le sens saisi, on peut oublier les mots. Cette image, qui sera abondamment reprise par le Chan ultérieur, articule deux thèses essentielles : la primauté de la compréhension directe sur la médiation textuelle, et la disponibilité immédiate de la vérité à qui sait la voir. ==== Hongren, Shenxiu, Huineng : le récit hagiographique de la transmission ==== L'école Chan se constitue effectivement aux VII{{e}} et VIII{{e}} siècles. Le cinquième patriarche Hongren (弘忍, 602-674), au monastère de Huangmei, élabore un enseignement que la tradition du Chan du Sud associera fortement au ''Sūtra du Diamant'' (金剛經, ''Jingang jing''), même si les débuts du Chan se rattachent également à d'autres corpus, notamment au ''Laṅkāvatāra-sūtra'' (楞伽經). Sa succession donne lieu, en 734, à une controverse mémorable, conduite par Shenhui (神會, 670-760), prêcheur méridional et ami de Wang Wei et de Du Fu, qui conteste la légitimité de Shenxiu (神秀, vers 605-705), chef du « Chan du Nord », et soutient que la véritable succession est revenue secrètement à Huineng (慧能, 638-713), futur fondateur du « Chan du Sud ».<ref>Cheng, ''Histoire de la pensée chinoise'', op. cit., p. 428-431. Sur la controverse de Shenhui, voir Jacques Gernet, ''Entretiens du maître de dhyāna Shen-houei du Ho-tsö'', Hanoi, École française d'Extrême-Orient, 1949 (rééd. Paris, Adrien-Maisonneuve, 1977).</ref> Le récit, codifié dans le ''Sūtra de l'Estrade du sixième patriarche'' (六祖壇經, ''Liuzu Tan jing''), oppose deux ''gāthās''. Shenxiu, présumé successeur, aurait proposé : « Le corps est l'arbre de l'Éveil, l'esprit, comme un miroir clair : sans cesse on doit l'essuyer afin qu'il reste sans poussière. » Huineng, alors humble pileur de riz illettré, aurait répliqué : « L'Éveil n'a pas d'arbre, le miroir clair n'a pas non plus de monture ; dans l'origine il n'y a rien : où la poussière pourrait-elle se poser ? »<ref>Pour le ''Sūtra de l'Estrade'' et la controverse des stances, voir Philip B. Yampolsky (trad.), ''The Platform Sutra of the Sixth Patriarch'', New York, Columbia University Press, 1967 ; en français, Patrick Carré (trad.), ''Soûtra de l'Estrade du sixième patriarche Houei-neng'', Paris, Seuil, 1995. Les deux stances sont commentées par Cheng, ''Histoire de la pensée chinoise'', op. cit., p. 429-430.</ref> Hongren aurait reconnu dans la seconde stance la véritable compréhension et transmis la robe patriarcale à Huineng. Il faut souligner que ce récit appartient au registre hagiographique : il sert à fonder rétrospectivement la primauté du Chan du Sud sur le Chan du Nord, dans un contexte de rivalité doctrinale entre les deux courants. Les recherches modernes ont montré que la version reçue du ''Sūtra de l'Estrade'' a été composée bien après les événements qu'elle prétend rapporter, et que l'opposition entre éveil graduel (漸悟, ''jianwu'', attribué à Shenxiu) et éveil subit (頓悟, ''dunwu'', attribué à Huineng) doit être lue comme une polémique d'école plus que comme une distinction biographique nette.<ref>Sur le caractère composite du ''Sūtra de l'Estrade'' et la construction de l'opposition Nord-Sud, voir John R. McRae, ''The Northern School and the Formation of Early Ch'an Buddhism'', Honolulu, University of Hawai'i Press, 1986 ; et la mise au point dans Bernard Faure, ''The Will to Orthodoxy: A Critical Genealogy of Northern Chan Buddhism'', Stanford, Stanford University Press, 1997.</ref> ==== Les méthodes Chan ==== Sous les Tang et les Song, le Chan se diffracte en plusieurs maisons (五家, ''wu jia'', les « cinq maisons »), qui développent chacune des méthodes spécifiques d'enseignement. L'école Hongzhou (洪州), animée par Mazu Daoyi (馬祖道一, 709-788), promeut la formule « l'esprit même est Bouddha » (即心即佛, ''ji xin ji fo''). Le maître Linji Yixuan (臨濟義玄, mort en 866), fondateur de l'école Linji, recourt à des chocs verbaux et physiques (cris, coups de bâton, formules paradoxales) destinés à interrompre brusquement le travail discursif de l'esprit du disciple. Sa déclaration la plus célèbre, qu'il convient de comprendre comme une figure rhétorique et non comme un programme : « Si vous rencontrez un Bouddha, tuez le Bouddha. Si vous rencontrez un patriarche, tuez le patriarche... C'est le moyen de la délivrance ».<ref>Cheng, ''Histoire de la pensée chinoise'', op. cit., p. 432. Pour Linji, voir Paul Demiéville (trad.), ''Entretiens de Lin-tsi'', Paris, Fayard, 1972, p. 117-118 pour le passage cité.</ref> Toute attache, fût-elle au Bouddha ou au patriarche, est encore un attachement, donc un obstacle. L'école Caodong (曹洞), au contraire, privilégie la méditation assise silencieuse (默照禪, ''mozhao chan'', « Chan de l'illumination silencieuse ») et trouve un prolongement important au Japon dans la lignée Sōtō. Les ''gong'an'' (公案, japonais ''kōan''), qui prennent leur essor sous les Song, sont de brèves anecdotes ou questions paradoxales servant de support à la méditation : « De quoi a l'air le Bouddha ? D'un bâton de fumier séché. » « Quel est le bruit d'une seule main qui applaudit ? » Ces énoncés ne sont pas des énigmes à résoudre intellectuellement, mais des instruments destinés à épuiser la prétention discursive de la pensée jusqu'à ce qu'elle s'ouvre à une compréhension non médiée.<ref>Sur les ''gong'an'', voir Steven Heine et Dale S. Wright (dir.), ''The Kōan: Texts and Contexts in Zen Buddhism'', New York, Oxford University Press, 2000.</ref> ==== Le Chan et la survie après la persécution de 845 ==== La grande persécution du bouddhisme conduite sous l'empereur Wuzong des Tang (武宗) en 845, qui détruisit des milliers de monastères et força au retour à la vie laïque plus de deux cent cinquante mille moines et nonnes, affecta gravement le bouddhisme institutionnel. Le Chan en sortit comparativement renforcé, pour plusieurs raisons que résume Anne Cheng : il était ressenti comme « proprement chinois » ; il ne présentait pas, à la différence des écoles dévotionnelles, un appareil rituel coûteux susceptible de provoquer l'hostilité confucéenne ; ses moines, tenus par la règle de l'école Hongzhou aux travaux manuels quotidiens (« un jour sans travail, un jour sans nourriture », formule attribuée à Baizhang Huaihai, 749-814), échappaient à l'accusation de parasitisme.<ref>Cheng, ''Histoire de la pensée chinoise'', op. cit., p. 433-434.</ref> Sous les Song, le Chan s'institutionnalise, codifie ses méthodes et s'impose comme l'interlocuteur bouddhique privilégié de la culture lettrée néo-confucéenne. === L'esthétique du Chan === Le Chan n'est pas une école d'art, mais il a durablement informé la pratique artistique et la réflexion esthétique chinoise. Wang Keping propose de regrouper sa contribution sous quatre traits cardinaux : la sagesse poétique (issue de la ''gāthā''), l'éveil subit, le « sens Chan » (禪意, ''chan yi'') et le « vide subtil » (空靈, ''kong ling'').<ref>Wang Keping, « A General Introduction to Chinese Aesthetics », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 1, section « The Pursuit of Chan Buddhism ».</ref> ==== Sagesse poétique et ''gāthā'' ==== Une ''gāthā'' est, dans la tradition bouddhique, une brève stance destinée à condenser une réalisation spirituelle. La stance de Huineng citée plus haut en est l'exemple paradigmatique. Sa forme, courte et paradoxale, vise à transmettre l'apparition immédiate de la vérité plutôt qu'à l'expliquer. Cette pratique a produit, en marge ou en prolongement du Chan, une poésie philosophique de l'éclat soudain qui se distingue tant de la poésie de remontrance morale (courant confucéen) que de la poésie d'évasion vers la nature (courant taoïste). ==== L'éveil subit et le « miao wu » ==== L'éveil subit (頓悟) est, dans son emploi esthétique, parfois nommé « éveil subtil » (妙悟, ''miao wu''). Le terme fait pendant esthétique au ''dunwu'' doctrinal : il désigne l'apparition non discursive d'une compréhension complète, mystérieuse, ineffable. Yan Yu (嚴羽, XIII{{e}} siècle), critique poétique des Song du Sud, fait du ''miao wu'' la qualité essentielle de la grande poésie dans son ''Canglang shihua'' (滄浪詩話, « Propos sur la poésie de Canglang ») : la grande poésie ne s'apprend pas, elle survient ; elle ne se prouve pas, elle se reconnaît.<ref>Pour le ''Canglang shihua'' de Yan Yu et l'usage de ''miao wu'', voir Stephen Owen, ''Readings in Chinese Literary Thought'', Cambridge (Mass.), Harvard University Asia Center, 1992, p. 391-420 ; et la discussion dans Wang Keping, art. cit.</ref> Cette esthétique du ''miao wu'' ne s'oppose pas à la discipline. Comme l'a souligné Li Zehou, l'éveil subtil suppose une longue préparation et une lente sédimentation des règles dans le geste artistique. Il s'apparente à ce point au ''ziran'' du Cuisinier Ding de Zhuangzi, autre figure d'un acquis devenu invisible. ==== Le sens Chan (''chan yi'', 禪意) ==== Le ''chan yi'' désigne une qualité d'attention et de réceptivité, dans laquelle l'esprit, selon la lecture de Li Zehou, laisse paraître une dimension durable ou non objectivable à travers le flux du sensible. Li Zehou en propose une analyse précise dans son chapitre sur les « quêtes métaphysiques » : « Le Chan ne nie pas le monde sensible ni l'existence humaine perceptuelle, soutenues par les deux traditions [confucéenne et taoïste]. Il ne nie pas non plus l'affirmation confucéenne de la vie quotidienne. Là où les confucéens disent : "la Voie se trouve dans les relations humaines quotidiennes", le Chan enseigne : "porter de l'eau et fendre du bois, il n'y a rien là qui ne soit la Voie excellente" ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 161. Traduction nôtre.</ref> Le poème emblématique du ''chan yi'' est le ''Lu Zhai'' (鹿柴, « Pavillon des cerfs ») de Wang Wei : « Montagne vide, on n'y voit personne, on entend seulement l'écho des voix. La lumière revenue pénètre la forêt profonde, et rejaillit sur la mousse verte. » (空山不見人,但聞人語響。返景入深林,復照青苔上。) Tout, dans la scène, est familier et tranquille. Il y a du mouvement dans la quiétude, de la plénitude dans le vide, de la beauté dans la vacance. Wang Keping commente : « le noumène transcende ces aspects et, en lui, ils se confondent et deviennent inséparables. C'est ainsi que l'on peut atteindre le noumène à travers le monde phénoménal pluriel, ou l'éternité dans la compréhension intuitive d'un instant ».<ref>Wang Keping, art. cit., section « The Sudden Awakening of the Chan Sense ». Traduction nôtre.</ref> Une correction philologique est ici nécessaire. Un passage de l'article antérieur attribuait à Wang Wei le vers « dans les montagnes vides, personne, l'eau coule et les fleurs s'épanouissent » (空山不見人,水流花開). Comme le note Li Zehou, ce vers n'est pas de Wang Wei mais de Su Shi : « In the empty hills there is no one, / Flowers bloom and water flows ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 169 : « the lines of Su Shi, one of the foremost poets of the Song dynasty, "In the empty hills there is no one, / Flowers bloom and water flows," are Chan, not Daoist ».</ref> Li Zehou utilise précisément ce vers pour exemplifier ce qui sépare le sens Chan du sens taoïste : « ces vers, en surface, décrivent la beauté (la nature), mais ce qu'ils désignent est le vide (vide noumenal). À l'inverse, les phrases de Zhuangzi décrivent le vide, mais ce qu'elles désignent est en réalité la plénitude (la personnalité humaine ultime) ».<ref>Ibid. Traduction nôtre.</ref> Li Zehou propose, pour rendre sensible cette distinction subtile, une comparaison de quatre couplets de Du Fu, Li Bo, Wang Wei et Tao Qian portant sur des images naturelles voisines, et conclut : « Les vers de Du Fu suggèrent un activisme confucéen tourné vers ce monde ; ceux de Li Bo, une ampleur d'esprit taoïste insouciante ; et ceux de Wang Wei, un contentement éclairé par le Chan ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 169-170. Traduction nôtre.</ref> Il note immédiatement que ces partages doivent être maniés avec prudence : Wang Wei et Su Shi sont « extérieurement confucéens mais Chan bouddhistes et taoïstes au cœur », et le confucianisme, le taoïsme et le Chan « ne sont pas toujours faciles à démêler l'un de l'autre ».<ref>Ibid., p. 170. Traduction nôtre.</ref> ==== Le vide subtil (''kong ling'', 空靈) ==== Le ''kong ling'', traduit par « vide subtil » ou « vide animé », est l'une des catégories que Wang Keping rattache le plus directement à l'héritage Chan. La notion est en réalité tributaire d'un entrelacs d'apports bouddhistes, taoïstes, lettrés et picturaux, mais elle reçoit dans la critique poétique post-Tang une coloration spécifiquement Chan. Wang Keping en analyse la structure en trois scènes poétiques, traditionnellement utilisées pour illustrer les stades de la culture du ''dhyāna'' : « Partout les collines sauvages sont couvertes de feuilles tombées, où trouverai-je un sentier battu pour en sortir ? » Cette première scène figure la recherche encore extérieure, agitée, du Chan. Vient ensuite : « Dans les collines sauvages, personne ; mais l'eau coule et les fleurs fleurissent. » Cette deuxième scène, qui correspond au vers de Su Shi évoqué plus haut, figure un stade intermédiaire : la tranquillité est gagnée, mais le pratiquant distingue encore les objets en tant qu'objets. Enfin : « Le ciel large existe éternellement, tout le paysage advient en un seul matin. » Cette troisième scène figure l'éveil consommé, où l'éternité est saisie dans l'instant et où l'opposition entre le moment et la durée se dissout.<ref>Wang Keping, art. cit., section « The Working of the Subtle Void ». Traduction nôtre. Les trois scènes appartiennent à la littérature classique du Chan ; Wang Keping en propose ici une systématisation pédagogique.</ref> Devenu critère d'évaluation artistique, le ''kong ling'' favorise la contemplation de ce qui paraît vide, serein, profond, mystérieux. Il privilégie l'éveil soudain de l'infini dans le fini, de la profondeur dans la simplicité, de l'éternité dans un instant. Sous son influence, les artistes chinois ont fait leur des formules comme « le vide peut accueillir les dix mille royaumes », « l'infini se laisse percevoir dans le fini », « les mots sont à oublier une fois le sens saisi », « ce qui n'est pas factuel et ce qui est factuel s'engendrent réciproquement », « la brillance vivante se signifie par un minimum de description verbale ».<ref>Wang Keping, art. cit. Ces formules condensent un siècle de critique poétique et picturale Song-Ming.</ref> Ces principes ont marqué surtout la poésie et la peinture lettrée, avec des prolongements dans la calligraphie et l'art des jardins. La peinture monochrome de paysage des Song et des Yuan, dont les œuvres de Ni Zan (倪瓚, 1301-1374) et de Huang Gongwang (黃公望, 1269-1354) restent des sommets, en offre les exemples les plus célèbres. Une tradition plus spécifiquement liée aux monastères Chan produit, sous les Song du Sud, une peinture à l'encre rapide et abréviative, dite « Chan painting ». Les moines-peintres Liang Kai (梁楷, vers 1140-1210) et Muqi Fachang (牧谿法常, vers 1210-1269) en sont les figures les plus connues. Les portraits gestuels de Liang Kai (''Li Bai en train de marcher'', ''Le sixième patriarche déchirant un sūtra''), exécutés en quelques coups de pinceau, et les compositions de Muqi (''Six kakis'', ''Goutte d'eau et fruits'', ''Singe et louveteau'') illustrent une économie de moyens où le vide laissé sur la soie a une fonction structurelle. Cette peinture, marginale en Chine, exerça en revanche une influence durable sur la tradition japonaise du ''suiboku'' (水墨), notamment à travers la collection d'Ashikaga Yoshimasa au XV{{e}} siècle.<ref>Sur la peinture Chan et son destin japonais, voir Helmut Brinker et Hiroshi Kanazawa, ''ZEN: Masters of Meditation in Images and Writings'', Zurich, Artibus Asiae, 1996 ; et James Cahill, ''Hills Beyond a River: Chinese Painting of the Yuan Dynasty, 1279-1368'', New York, Weatherhill, 1976. Sur les usages chinois vs japonais, voir aussi Yukio Lippit, « Of Modes and Manners in Japanese Ink Painting: Sesshū's Splashed Ink Landscape of 1495 », ''Art Bulletin'' 94, no. 1 (2012).</ref> ==== Chan et fadeur (''dan'', 淡) ==== Li Zehou souligne un dernier trait : le sens Chan, lorsqu'il imprègne l'art, prend la forme d'une « saveur prolongée » (餘味, ''yu wei'') et d'une « fadeur » (淡, ''dan''). Ce ''dan'', à distinguer du « parfum de souffle » (氣韻, ''qiyun'') ou du « parfum divin » (神韻, ''shenyun'') des Wei-Jin, est « complètement débarrassé de toute notion de force, d'élévation, de grâce ou d'élégance, et devient une saveur prolongée totalement mondaine, ici-bas, et en même temps profondément illusoire dans son caractère ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 178-179. Traduction nôtre.</ref> L'exemple emblématique en est, pour Li Zehou, la peinture de Ni Zan : « Au pied du pavillon je ne rencontre personne, / Pâles ombres d'automne au soleil couchant »<ref>Ibid., p. 179. Vers de Ni Zan.</ref>. Le pavillon est vide, la lumière est faible, rien ne se passe. C'est dans cette absence presque rien que se laisse pressentir, par fugitive ressemblance, le noumène éternel. Quand on tend la main pour le saisir, il s'est dérobé. Cette fadeur du Chan rejoint, sans s'y confondre, la fadeur du Laozi et du Huainanzi évoquée dans la section précédente : pour les courants taoïsants, la fadeur est saveur du Dao ; pour le Chan, elle est mode d'apparition du noumène vide. Li Zehou maintient soigneusement la distinction : « Les phrases de Zhuangzi, "monter sur les nuages et le vent, enfourcher le soleil et la lune, voyager au-delà des quatre mers", sont taoïstes, non Chan ; les vers de Su Shi, "dans les collines vides, personne, les fleurs s'épanouissent et l'eau coule", sont Chan, non taoïstes ».<ref>Ibid., p. 169.</ref> La différence tient au pôle vers lequel pointe l'image : la plénitude humaine ultime pour le taoïsme, le vide noumenal pour le Chan. ==== Une relecture contemporaine : l'infra-mince et la « cinquième dimension » ==== Il convient ici de quitter le terrain des catégories traditionnelles chinoises pour signaler une relecture savante contemporaine. La notion d'« infra-mince » est empruntée à Marcel Duchamp ; celle de « cinquième dimension » est forgée par François Cheng dans ''Souffle-Esprit'' (1989). Aucun des deux concepts n'appartient à la tradition esthétique chinoise classique ; ils servent à éclairer rétrospectivement la poétique du vide à l'aide d'instruments modernes. Cette relecture est due au philosophe Xia Kejun, qui propose une analyse phénoménologique du ''Lu Zhai'' de Wang Wei. Dans cette lecture, la « montagne vide » de Wang Wei n'est pas une montagne avec quelque chose en moins (l'homme), mais l'apparition d'une non-dimensionnalité qui rend possible le déploiement de l'espace pictural. L'écho des voix devient une pseudo-une-dimensionnalité ; le rayon de soleil pénétrant la forêt, une quatrième dimension temporelle ; le reflet sur la mousse verte, une cinquième dimension où tout se rassemble dans la ténuité.<ref>Xia Kejun, « Nature as Not-yet-existing Beauty: Infra-thin Poetic Art of Enchorial-topia », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 7.</ref> Comme l'écrit François Cheng, cette cinquième dimension est « le vide qui transcende l'espace-temps, l'état suprême vers lequel tend toute peinture inspirée par la vérité ».<ref>François Cheng, ''Souffle-Esprit. Textes théoriques chinois sur l'art pictural'', Paris, Seuil, 1989 (rééd. « Points Essais », 2006), cité par Xia Kejun, art. cit.</ref> Cette relecture, qui mobilise Walter Benjamin, Marcel Duchamp et la phénoménologie, ne prétend pas restituer le Chan classique ; elle signale combien l'esthétique chinoise du vide demeure productive dans la pensée contemporaine. Elle invite à considérer le ''kong ling'' non comme un trait archaïque d'une tradition close, mais comme une ressource pour penser, en régime moderne, les rapports entre image, monde et négativité. === Synthèse === L'esthétique du vide, dans la tradition bouddhiste sinisée, n'est pas une thèse unique mais le croisement de plusieurs élaborations distinctes. La doctrine de la Perfection de la Sagesse fournit la formulation centrale (« la forme est vide »), reprise et systématisée par Nāgārjuna autour de la coproduction conditionnée, puis réacclimatée en Chine par Sengzhao au prix d'un travail terminologique qui réinvestit le vocabulaire du Laozi et du Zhuangzi. Le Chan, qui s'élabore sous les Tang en marge des grandes écoles doctrinales, articule cette doctrine à la pratique : éveil subit, attention au présent, ouverture aux gestes ordinaires (porter de l'eau, fendre du bois). Sur cette base se déploie une esthétique du « vide subtil » (''kong ling'') qui informe surtout la poésie (quatrains de Wang Wei, ''shi'' de Su Shi) et la peinture lettrée, avec des prolongements dans la calligraphie et l'art des jardins. Cette esthétique n'oppose pas le sensible à l'intelligible, ni la beauté au vide. Elle pense le sensible comme un mode d'apparition du vide, et le vide comme la condition pour que le sensible n'épuise pas le réel. Elle se distingue de l'esthétique taoïsante, à laquelle elle doit beaucoup, par un déplacement subtil : ce que vise l'image, selon les lectures Chan, n'est pas la plénitude inépuisable du Dao, mais une profondeur non objectivable qui se laisse entrevoir dans l'évanescence du phénomène. Il faut préciser que ce vocabulaire (noumène, profondeur, éternel) appartient à une lecture esthétique moderne, en particulier celle de Li Zehou, et non au Madhyamaka lui-même, dont la doctrine du vide sert au contraire à défaire l'attachement aux essences. Cette esthétique se distingue également des dépréciations monastiques de la beauté sensible, qui appartiennent à un autre registre, ascétique et pédagogique, dont les visées et les destinataires sont précisément définis. Comme l'a souligné Li Zehou, Wang Wei et Su Shi sont les figures où cette synthèse atteint son point d'équilibre : « extérieurement confucéens, mais Chan bouddhistes et taoïstes au cœur ».<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 170.</ref> En eux, et dans la lignée critique qui les a commentés depuis les Song jusqu'à François Cheng et Xia Kejun, l'esthétique chinoise du vide demeure l'une des contributions les plus singulières à la réflexion universelle sur l'image, le sensible et la pensée. == Principes esthétiques de la peinture chinoise classique == La théorie picturale chinoise classique ne se ramène pas à un système unifié. Elle s'est plutôt élaborée comme un faisceau de catégories de longue durée, formulées à des époques distinctes et reprises, reformulées, déplacées d'un genre à l'autre : peinture de portrait, peinture de paysage, calligraphie, poésie. Les pages qui suivent en examinent trois articulations majeures : les Six Principes (六法, ''liufa'') attribués à Xie He au début du VI{{e}} siècle, qui ont fourni à la culture lettrée un vocabulaire critique durable ; la notion de ''chuanshen'' (傳神, « transmettre l'esprit »), associée à Gu Kaizhi un siècle plus tôt, qui pose une question proprement esthétique du portrait ; et la notion de ''xiangwai'' (象外, « au-delà de l'image »), qui se déploie de la critique picturale à la poétique des Tang et au-delà. Ces trois catégories ne sont pas étrangères les unes aux autres, mais elles ne forment pas non plus un système clos : leur cohérence est rétrospective, produite par l'histoire des commentaires plutôt que par les textes premiers. === Les Six Principes de Xie He === [[Fichier:Gu Kaizhi 001.jpg|thumb|right|300px|''Admonitions de la préceptrice aux dames du palais'', attribué à Gu Kaizhi (IV{{e}} siècle)]] Le ''Guhua pin lu'' (古畫品錄, ''Registre de classification des peintures anciennes'') de Xie He (謝赫, actif vers 500-535) est le plus ancien classement systématique de peintres chinois qui nous soit parvenu. Sa préface contient l'énoncé des Six Principes, formule courte et difficile devenue le texte de référence de la théorie picturale chinoise. La biographie de Xie He demeure presque entièrement inconnue ; les rares informations le décrivent comme un portraitiste de cour de talent mais sans relief. Le traité lui-même est généralement daté, sur la base des peintres qu'il évalue, des années 532-549, c'est-à-dire de la dynastie Liang (502-557) et non, comme on le lit parfois, des Qi du Sud (479-502), période où l'activité de Xie He aurait simplement commencé.<ref>Victor H. Mair, « Xie He's "Six Laws" of Painting and Their Indian Parallels », dans Zong-qi Cai (éd.), ''Chinese Aesthetics: The Ordering of Literature, the Arts, and the Universe in the Six Dynasties'', Honolulu, University of Hawai'i Press, 2004, p. 81-122, ici p. 82 et notes 4-5.</ref> ==== Une formulation difficile et sa reformulation par Zhang Yanyuan ==== Les Six Principes posent un problème philologique avant tout problème herméneutique. Dans la forme où Xie He les énonce, ils consistent en six segments brefs construits comme « N (numéro) R S, ''shi ye'' (« voilà ce que c'est ») », où R est un binôme « élégant » d'origine littéraire et S un binôme plus descriptif et technique. La grammaire de cette construction est inhabituelle et a longtemps déconcerté les commentateurs. Au milieu du IX{{e}} siècle, Zhang Yanyuan (張彥遠, vers 815-877), dans son ''Lidai minghua ji'' (歷代名畫記, ''Registre des peintures célèbres de toutes les dynasties''), reformule discrètement les six énoncés en « N ''yue'' (« on l'appelle ») R S », ce qui supprime la pause logique entre R et S et permet de lire chaque principe comme une seule unité quadrisyllabique. Cette reformulation s'est imposée pour plus de mille ans et c'est elle que reprennent les histoires de l'art chinoises et occidentales.<ref>Mair, « Xie He's "Six Laws" », op. cit., p. 86-89. Mair propose une analyse philologique détaillée de cette transformation grammaticale et de ses conséquences interprétatives.</ref> Une fois cette stratification reconnue, deux lectures coexistent. La lecture traditionnelle, héritée de Zhang Yanyuan, traduit le premier principe par « résonance vitale et animation vivante » (氣韻生動, ''qiyun shengdong'') comme une qualité unique. La restitution philologique proposée par Victor Mair lit plutôt « résonance vitale, qui est l'engendrement du mouvement », chaque principe énonçant un terme de critique apprécié des lettrés (R) et son contenu pratique (S). Selon cette lecture, Xie He aurait commencé par identifier les six dimensions techniques de la peinture (S), puis aurait choisi pour chacune un terme de critique littéraire prestigieux (R) afin d'en élever le statut esthétique.<ref>Mair, ''ibid.'', p. 93-97 et 103-105.</ref> Indépendamment de cette analyse interne, Qian Zhongshu (錢鍾書, 1910-1998) a contesté la lecture habituelle du premier principe : pour lui, ''shengdong'' n'est pas un complément adjectival qualifiant ''qiyun'' (« la résonance vitale doit être animée »), mais une définition (« la résonance vitale est l'animation »). Cette correction concentre l'attention sur ''qiyun'' comme catégorie centrale de la critique picturale plutôt que sur un idéal de mouvement.<ref>Zong-qi Cai, « The Conceptual Origins and Aesthetic Significance of "Shen" in Six Dynasties Texts on Literature and Painting », dans Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 310-342, ici p. 329-330.</ref> ==== Six Principes : énoncé et portée ==== Suivant l'ordre du texte, les six principes peuvent être restitués comme suit, en signalant entre crochets les écarts entre la lecture traditionnelle et la lecture philologique. Le premier, ''qiyun shengdong'' (氣韻生動, « résonance vitale [et] engendrement du mouvement »), reste la formule la plus commentée. ''Qi'' (氣) désigne le souffle, l'énergie vitale ; ''yun'' (韻) la résonance, l'harmonie. La paire est attestée dans la critique littéraire des Six Dynasties avant Xie He et y désigne une qualité d'allure subtile que l'on perçoit chez une personne ou dans une œuvre.<ref>Cai, « "Shen" », op. cit., p. 330-332. Cai documente plusieurs occurrences pré-Xie He de ''qiyun'' dans des jugements de caractère du genre ''qingtan''.</ref> Dans la peinture, ''qiyun'' désigne moins une technique qu'une qualité globale, perçue comme animant l'œuvre ; Xie He s'en sert pour distinguer les peintres de premier rang de ceux qui ne maîtrisent que les aspects matériels du métier. Le deuxième, ''gufa yongbi'' (骨法用筆, « méthode de l'os, [c'est-à-dire] usage du pinceau »), associe la pratique du pinceau à la métaphore de l'ossature : la qualité d'un trait dépend de la structure interne qu'il manifeste, comme un corps de la solidité de son squelette. La métaphore connecte directement la peinture et la calligraphie, dont les théories partagent ce vocabulaire d'osseux et de charnu. Jing Hao (荊浩, actif vers la fin du IX{{e}} siècle), dans son ''Bifa ji'' (筆法記, ''Notes sur la méthode du pinceau''), distinguera ainsi quatre qualités du trait : le nerf (筋, ''jin''), la chair (肉, ''rou''), l'os (骨, ''gu'') et le souffle ou la vigueur (氣, ''qi'').<ref>Susan Bush et Hsio-yen Shih (éd.), ''Early Chinese Texts on Painting'', Cambridge (Mass.), Harvard University Press, 1985, p. 144-148.</ref> Le troisième, ''yingwu xiangxing'' (應物象形, « correspondre aux choses, [c'est-à-dire] figurer la forme »), porte sur la justesse de la représentation. La traduction de ''ying'' par « correspondre » est plus exacte que « imiter » : il s'agit moins d'une reproduction littérale que d'une résonance entre la forme picturale et la chose représentée.<ref>Bush et Shih, ''Early Chinese Texts'', op. cit., p. 17-19.</ref> Le quatrième, ''suilei fucai'' (隨類賦彩, « selon le type, [c'est-à-dire] appliquer la couleur »), porte sur la couleur, qui doit suivre les catégories d'objets représentés. À partir des Tang, le développement de la peinture monochrome à l'encre (水墨畫, ''shuimo hua'') déplacera ce principe : il faudra rendre la qualité chromatique d'une chose par l'encre seule, sans recours à la couleur.<ref>Zhang Yanyuan, ''Lidai minghua ji'', cité dans Bush et Shih, ''Early Chinese Texts'', op. cit., p. 49-50. Zhang lui-même évoque la possibilité de suggérer la couleur sans la peindre.</ref> Le cinquième, ''jingying weizhi'' (經營位置, « administrer et arranger, [c'est-à-dire] positionner et placer »), porte sur la composition spatiale. ''Jingying'' est un terme administratif et militaire ; son emploi pour la peinture suggère un travail réfléchi de gestion de l'espace pictural. Le sixième, ''chuanyi moxie'' (傳移模寫, lecture traditionnelle ; la forme originale chez Xie He pourrait avoir été ''chuanyi'' / ''moxie'') concerne la copie et la transmission des modèles. Mair note que ''chuanyi'' (傳移) est anormal et n'apparaît nulle part avant Xie He ; Zhang Yanyuan paraît l'avoir réécrit en ''chuanmo yixie'' (傳模移寫), forme qui s'est imposée par la suite.<ref>Mair, « Xie He's "Six Laws" », op. cit., p. 120, note 59.</ref> Dans la pratique des Six Dynasties, la copie peut désigner aussi bien le calque exact (摹, ''mo'') que l'imitation libre (臨, ''lin'') ou la copie d'après nature.<ref>Robert E. Harrist Jr., « Replication and Deception in Calligraphy of the Six Dynasties Period », dans Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 31-59, en particulier p. 45-49.</ref> ==== L'hypothèse d'une influence indienne ==== La proximité numérique et structurelle entre les Six Principes chinois et les Six Membres (षडङ्ग, ''ṣaḍaṅga'') de la peinture indienne, énumérés dans certains commentaires indiens à des textes en sanskrit, a été remarquée dès la fin du XIX{{e}} siècle. La question d'une influence directe demeure débattue. Pour Mair, la lecture restituée des Six Principes, dans laquelle le binôme « technique » (S) est primaire et le binôme « élégant » (R) ajouté pour le prestige littéraire, rend une parenté indienne possible et même probable, chaque S des Six Principes correspondant terme à terme à un membre du ''ṣaḍaṅga''. La position majoritaire chez les sinologues chinois reste cependant prudente : ''gufa yongbi'' et ''qiyun shengdong'' sont des produits manifestes de la critique chinoise antérieure, et l'hypothèse d'une influence reste à étayer plus solidement.<ref>Mair, ''ibid.'', p. 100-108 et p. 119, note 53 ; pour la position prudente, voir la citation de ''Zhongguo da baike quanshu: Meishu'' (1991), reproduite par Mair p. 115, note 32.</ref> ==== Hiérarchie et postérité des Six Principes ==== Bien que Xie He énonce les six principes comme une série, la tradition postérieure tend à reconnaître au premier une position particulière. Zhang Yanyuan le formule de manière nette : la résonance vitale ne se laisse pas apprendre, tandis que la maîtrise du pinceau peut s'enseigner ; sans la première, la seconde demeure vaine.<ref>Zhang Yanyuan, ''Lidai minghua ji'', cité dans Bush et Shih, ''Early Chinese Texts'', op. cit., p. 53-54.</ref> Cette hiérarchisation soulève une question récurrente dans la littérature des Song et au-delà : ''qiyun'' relève-t-il d'une disposition donnée à l'artiste, ou peut-il être cultivé par l'étude, la pratique et la conduite morale ? Les positions varient suivant les écoles, et la question s'enchevêtre avec les développements néo-confucéens autour du ''li'' (理, « principe »).<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, Honolulu, University of Hawai'i Press, 2010, p. 85-95, qui analyse l'évolution de l'interprétation des Six Principes des Tang aux Ming.</ref> L'autorité durable des Six Principes a pour effet que la plupart des traités picturaux postérieurs s'y réfèrent, soit pour les commenter, soit pour proposer leurs propres systèmes de critères (les « Six Essentiels » de Liu Daochun au XI{{e}} siècle, les « Six Forces » de Sheng Dashi sous les Qing, parmi d'autres). Au XX{{e}} siècle, l'expression ''liufa'' a même fini par fonctionner comme synonyme de « peinture » dans le vocabulaire critique.<ref>Mair, « Xie He's "Six Laws" », op. cit., p. 81.</ref> === Capter l'esprit au-delà de la forme (傳神, ''chuanshen'') === La notion de ''chuanshen'' (傳神, « transmettre l'esprit »), associée pour l'essentiel à Gu Kaizhi (顧愷之, vers 345 - vers 406), précède d'un peu plus d'un siècle l'énoncé des Six Principes. Elle relève d'une réflexion sur le portrait et plus particulièrement sur le visage humain ; sa généralisation aux autres genres picturaux et à la poésie est tardive et procède par déplacements analogiques. ==== Gu Kaizhi et la doctrine du portrait ==== Gu Kaizhi, peintre de la cour des Jin orientaux, n'a pas laissé d'écrit théorique systématique : ses positions sont préservées par citations dans le ''Lidai minghua ji'' de Zhang Yanyuan et par anecdotes dans le ''Shishuo xinyu'' (世說新語, ''Nouveaux récits des propos du monde'') compilé par Liu Yiqing (劉義慶, 403-444). Le passage le plus souvent cité figure dans la section « Habileté et art » (巧藝, ''Qiaoyi'') du recueil : « Gu Changkang [Gu Kaizhi] peignait parfois un portrait et laissait les pupilles non peintes pendant plusieurs années. Quand on l'interrogeait, il répondait : "La beauté ou la laideur des quatre membres n'a rien à voir avec ce qui fait le caractère miraculeux d'un portrait. Pour transmettre l'esprit et donner une représentation vivante (傳神寫照, ''chuanshen xiezhao''), c'est précisément en cet endroit-là que tout se joue [c'est-à-dire l'œil]" ».<ref>''Shishuo xinyu'', 21.13, dans Liu Yiqing, ''Shishuo xinyu jianshu'', éd. Yu Jiaxi, Beijing, Zhonghua shuju, 1983, p. 722. Traduction française adaptée de l'anglais de Richard B. Mather, ''Shih-shuo Hsin-yü: A New Account of Tales of the World'', Minneapolis, University of Minnesota Press, 1976, et de la traduction donnée par Zong-qi Cai, « "Shen" », op. cit., p. 316.</ref> D'autres anecdotes recueillies dans le même chapitre du ''Shishuo xinyu'' précisent cette doctrine. Lorsqu'un ami affligé d'un défaut oculaire refuse de poser pour un portrait, Gu propose d'estomper la pupille par la technique du « blanc volant » (飛白, ''feibai'') pour la faire ressembler à un nuage clair voilant le soleil. Lorsqu'il peint Pei Kai, il ajoute trois poils sur la joue pour rendre l'acuité du personnage, ce qui, selon les témoins de l'époque, transforme effectivement la perception du portrait.<ref>''Shishuo xinyu'', 21.9 et 21.11, dans Wai-yee Li, « ''Shishuo xinyu'' and the Emergence of Aesthetic Self-Consciousness in the Chinese Tradition », dans Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 237-276, ici p. 255-256.</ref> Zong-qi Cai propose de comprendre la notion de ''shen'' (神) chez Gu Kaizhi à l'aide du terme latin ''anima'' : non l'âme au sens religieux occidental, mais le foyer intime de la personnalité, qui se manifeste à travers le corps sans en être indépendant. L'œil, en cette acception, n'est pas symbole mais lieu effectif où l'intériorité affleure ; toute l'attention du portraitiste doit s'y concentrer.<ref>Cai, « "Shen" », op. cit., p. 315-319. Cai distingue plusieurs strates dans le vocabulaire du ''shen'' aux Six Dynasties et montre que la lecture de Gu Kaizhi mobilise spécifiquement la tradition philosophique du ''xing-shen bing zhong'' (« corps et esprit ensemble »), héritée du ''Huainan zi'' et de Wang Chong.</ref> ==== ''Chuanshen'' et ''qiyun'' : deux notions distinctes ==== Les commentaires postérieurs tendent à fondre ''chuanshen'' et ''qiyun'' en une seule théorie de l'« expression de l'esprit ». Cai propose au contraire de les distinguer. Pour Gu Kaizhi, ''shen'' désigne le foyer de la personnalité d'un sujet particulier, perçu à travers ses traits ; pour Xie He, ''qiyun'' désigne plutôt une qualité d'ensemble de l'œuvre, un effet esthétique global qui peut s'apparenter à une dimension « transcendante » dans le sens où elle déborde la simple représentation. Quand Xie He parle du ''shen'' d'un peintre, il l'associe à des termes comme « subtil et miraculeux » (微妙, ''weimiao''), « au-delà de l'image » (象外, ''xiangwai'') ou « spectacle merveilleux » (奇觀, ''qiguan'') ; quand Gu en parle, il pense d'abord à la singularité d'un visage rendu vivant par la justesse d'un détail.<ref>Cai, ''ibid.'', p. 332-334.</ref> Les deux notions sont apparentées mais ne se recouvrent pas, et la distinction permet de mieux comprendre comment la théorie picturale chinoise a élaboré, à partir du V{{e}} et du VI{{e}} siècle, deux registres distincts de la spiritualité de l'œuvre. ==== Forme et esprit : ''xingsi'' et ''shensi'' ==== À partir des Tang, la critique picturale formule plus explicitement la distinction entre ressemblance formelle (形似, ''xingsi'') et ressemblance d'esprit (神似, ''shensi''). La première rend l'apparence ; la seconde rend l'allure intérieure. Cette distinction n'est pas une dévaluation pure et simple de la ressemblance formelle : un portrait sans justesse des traits manque sa cible. Mais la ressemblance d'esprit est considérée comme un niveau supplémentaire que le seul rendu des traits ne garantit pas.<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 102-108.</ref> Su Shi (蘇軾, 1037-1101), un des théoriciens les plus influents du déplacement de l'accent vers la ressemblance d'esprit, écrit ainsi qu'« évaluer une peinture sur sa seule ressemblance d'apparence, c'est avoir une compréhension proche de celle d'un enfant ». Cette formule reprise dans la critique des Song et des Yuan contribue à fonder la posture du peintre lettré : la peinture n'a pas pour vocation la copie exacte du monde mais l'expression d'une qualité intérieure que la copie exacte tend à masquer.<ref>Su Shi, poème adressé à Yan Lingbin, traduit dans Susan Bush, ''The Chinese Literati on Painting'', Cambridge (Mass.), Harvard University Press, 1971, p. 25-26. Sur le déplacement plus large opéré par Su Shi et ses contemporains, voir Bush, ''ibid.'', p. 29-83.</ref> ==== Le ''chuanshen'' au-delà du portrait : paysage et calligraphie ==== À mesure que la peinture de paysage (山水畫, ''shanshui hua'') s'autonomise à partir des Six Dynasties, la doctrine du ''chuanshen'' s'y trouve étendue par analogie. Le paysage n'est plus seulement un cadre, mais possède lui-même un « esprit » que le peintre doit saisir. Cette transposition n'a rien d'évident et procède d'une longue élaboration. La première théorie systématique du paysage est celle de Zong Bing (宗炳, 375-443) dans son « Préambule à la peinture de paysage » (畫山水序, ''Hua shanshui xu'') et celle de Wang Wei (王微, 415-453, à distinguer du poète Tang) dans son « Discussion de la peinture » (敘畫, ''Xu hua''). Tous deux conçoivent la peinture comme accédant à une « spiritualité » (靈, ''ling'') de la nature, dans un cadre cosmologique inspiré du ''Xuanxue'' et nourri, dans le cas de Zong Bing, par la dévotion bouddhiste.<ref>Susan Bush, « The Essay on Painting by Wang Wei (415-453) in Context », dans Cai (éd.), ''Chinese Aesthetics'', op. cit., p. 60-80. Bush rappelle p. 60 que le ''Xu hua'' est généralement classé sous l'étiquette de « daoïsme du paysage », par contraste avec le « bouddhisme du paysage » de Zong Bing.</ref> L'élaboration la plus systématique vient toutefois de Guo Xi (郭熙, vers 1020 - vers 1090), peintre et théoricien des Song du Nord. Son traité ''Linquan gaozhi'' (林泉高致, ''Hautes aspirations des forêts et des sources''), compilé par son fils Guo Si, distingue trois types de profondeur dans la composition du paysage : la profondeur élevée (高遠, ''gaoyuan''), de bas en haut ; la profondeur lointaine (深遠, ''shenyuan''), du devant vers l'arrière à travers les masses ; et la profondeur plane (平遠, ''pingyuan''), d'un avant-plan jusqu'à un lointain horizontal. Cette typologie, souvent qualifiée à tort de « perspective » au sens occidental, désigne plutôt trois manières de structurer l'espace pictural sans point de fuite unique. L'expression moderne de « perspective dispersée » (散點透視, ''sandian toushi''), parfois utilisée pour la décrire, est forgée au XX{{e}} siècle et ne se trouve pas dans les sources classiques.<ref>Pour le passage classique, Guo Xi, ''Linquan gaozhi'', cité et traduit en partie dans Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 97. Sur l'invention moderne du terme ''sandian toushi'', voir notamment Wu Hung, ''A Story of Ruins: Presence and Absence in Chinese Art and Visual Culture'', Princeton, Princeton University Press, 2012, p. 18-20.</ref> Le poète et peintre Wang Wei (王維, vers 701-761), devenu dans la tradition postérieure une figure fondatrice de la peinture lettrée de paysage, n'a pas laissé d'écrit théorique conservé qui soit assurément de sa main : le ''Shanshui lun'' (山水論, ''De la peinture des montagnes et de l'eau'') et le ''Shanshui jue'' (山水訣, ''Secrets de la peinture des montagnes et de l'eau''), traditionnellement publiés sous son nom, sont considérés par la sinologie contemporaine comme des compilations tardives plutôt que comme des textes authentiques.<ref>Sur la transmission incertaine des textes attribués à Wang Wei le poète, voir Bush et Shih, ''Early Chinese Texts'', op. cit., p. 75-76 et 175-176, qui les classent parmi les « textes attribués ».</ref> En revanche, son rôle d'exemple pour les théoriciens postérieurs du paysage lettré, de Su Shi à Dong Qichang, est sûr. Dans la calligraphie, la transposition du ''chuanshen'' passe par le vocabulaire de la « peinture du cœur » (心畫, ''xinhua''), formule attestée chez Yang Xiong (53 av. - 18 apr. n. è.). La pratique calligraphique est conçue comme une mise en visibilité de la personne : son tempérament, sa probité, sa formation. La copie et l'imitation des maîtres anciens, loin d'être un défaut d'originalité, en sont une condition : l'apprenti, comme le rappelle un manuel chinois moderne, s'efforce non de reproduire les traits exactement mais d'« assimiler les qualités morales des anciens, incarnées dans leur trait ».<ref>Yolaine Escande, « Imitation, Personality and Expression in Chinese Calligraphy: The Inscription of the Self », dans Marcello Ghilardi et Chakravarthi Ram-Prasad (dir.), ''The Bloomsbury Research Handbook of Chinese Aesthetics and Philosophy of Art'', Londres, Bloomsbury, 2017, chap. 8.</ref> ==== Le ''shenyun'' à l'époque Qing ==== À l'époque Qing, le critique Wang Shizhen (王士禎, 1634-1711, à distinguer de l'homonyme Ming Wang Shizhen 王世貞, 1526-1590) reprend et systématise dans le champ poétique une catégorie déjà ancienne, le ''shenyun'' (神韻, parfois rendu en français par « charme spirituel »). Il propose une lecture de la poésie où le sens excède la dénotation : un bon poème n'épuise pas sa signification dans ce qu'il dit, mais laisse paraître une qualité allusive comparable à celle qu'un portrait de Gu Kaizhi tirait du seul détail de l'œil. Cette extension du vocabulaire pictural à la poésie n'est pas inédite ; elle culmine cependant chez Wang Shizhen en une véritable théorie critique, qui exercera une influence durable jusqu'à Wang Guowei.<ref>Karl-Heinz Pohl, « Rules and Living Rules in the Aesthetics of Chinese Painting and Poetry », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 7, qui retrace la généalogie du ''shenyun'' de Sikong Tu à Wang Shizhen ; et Richard John Lynn, « Orthodoxy and Enlightenment: Wang Shih-chen's Theory of Poetry and Its Antecedents », dans William Theodore de Bary (éd.), ''The Unfolding of Neo-Confucianism'', New York, Columbia University Press, 1975.</ref> === L'image au-delà de l'image (象外, ''xiangwai'') === La troisième catégorie centrale de l'esthétique picturale et poétique chinoise est celle du ''xiangwai'' (象外, « au-delà de l'image »). Elle prolonge à certains égards la doctrine du ''chuanshen'' mais s'en distingue : ''chuanshen'' désigne le passage de la forme à l'esprit dans un même sujet ; ''xiangwai'' désigne plutôt ce qui dans une œuvre excède toute forme assignable et reste à la fois suggéré par elle et irréductible à elle. ==== Une formule de Xie He et son destin ==== Le terme apparaît une première fois chez Xie He, dans une notice du ''Guhua pin lu'' sur les peintres Zhang Mo et Xun Xu : leurs œuvres, dit-il, « excellent à révéler les esprits subtils et laissent peu de traces de méthodes et de règles. Qui ne s'intéresse qu'à la représentation des choses réelles n'y verra guère de mérite ; mais qui s'intéresse à ce qui se tient au-delà de l'image (象外, ''xiangwai'') se détournera de la richesse et de l'opulence pour appeler ces peintures subtiles et merveilleuses ».<ref>Xie He, ''Guhua pin lu'', cité dans Cai, « "Shen" », op. cit., p. 333. Cai souligne que ''xiangwai'' fait partie du faisceau lexical par lequel Xie He caractérise le ''shen'' au-delà de la simple ressemblance.</ref> Cette formule, brève, n'aurait peut-être pas eu de postérité particulière si elle n'avait été reprise et déplacée dans la critique poétique des Tang. Liu Yuxi (劉禹錫, 772-842) écrit que « le monde [poétique] naît au-delà de l'image » (境生於象外, ''jing sheng yu xiangwai''). Sikong Tu (司空圖, 837-908), dans sa ''Lettre à Jipu'' (與極浦書, ''Yu Jipu shu''), reprend la formule en la doublant : la meilleure poésie est celle qui transmet « une image au-delà de l'image, un monde au-delà du monde » (象外之象,景外之景, ''xiangwai zhi xiang, jingwai zhi jing'').<ref>Sur la généalogie poétique du terme, voir Xia Kejun, « Mountains and Waters: Wang Wei and the Foundations of Chinese Landscape Painting », dans Ghilardi et Ram-Prasad (dir.), ''The Bloomsbury Research Handbook'', op. cit., chap. 6, qui cite les passages de Liu Yuxi et de Sikong Tu.</ref> La poétique de l'allusion, du retrait, du non-dit s'élabore dans cette mouvance ; les vingt-quatre catégories traditionnellement attribuées à Sikong Tu (二十四詩品, ''Ershisi shipin'') en sont la mise en forme la plus connue, en particulier les catégories « contenu et réservé » (含蓄, ''hanxu''), « limpide et sublime » (沖淡, ''chongdan'') et « transcendant » (超詣, ''chaoyi''). L'attribution même de ce traité à Sikong Tu a été discutée dans la philologie chinoise et occidentale du XX{{e}} siècle, mais son rôle dans la critique poétique demeure largement reconnu.<ref>Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 175-178, qui analyse les catégories sikongtuviennes dans leur rapport au ''chan'' et à la culture lettrée. Sur le débat d'attribution des ''Ershisi shipin'', voir Stephen Owen, ''Readings in Chinese Literary Thought'', op. cit., p. 299-300, et Pauline Yu, « Sikong Tu's ''Shipin'': Poetic Theory in Poetic Form », dans Ronald C. Miao (éd.), ''Studies in Chinese Poetry and Poetics'', vol. 1, San Francisco, Chinese Materials Center, 1978, p. 81-103.</ref> ==== Le paysage et le retrait de l'apparence ==== Dans la peinture de paysage, le principe du ''xiangwai'' se traduit techniquement par l'art de ne pas peindre tout. Guo Xi, dans le ''Linquan gaozhi'', en formule la règle : pour qu'une montagne paraisse haute, il ne suffit pas de la dessiner haute ; il faut que des brumes la cernent à mi-hauteur, ce qui laisse au spectateur l'imagination du sommet. Pour qu'une rivière paraisse longue, son cours ne doit pas être visible d'un bout à l'autre, mais s'interrompre dans une ombre, derrière un bouquet d'arbres, dans un repli. La technique consiste à « écrire le réel avec du vide » (以虛寫實, ''yi xu xie shi''), formule qui condense la dialectique entre ''xu'' (虛, vide, indéterminé) et ''shi'' (實, plein, déterminé) au cœur de la composition picturale chinoise.<ref>Guo Xi, ''Linquan gaozhi'', traduit en partie dans Bush et Shih, ''Early Chinese Texts'', op. cit., p. 168-178.</ref> François Jullien analyse longuement cette logique dans ''La Grande Image n'a pas de forme''. Il oppose la démarche dégagée par la peinture chinoise classique à une tendance dominante de la peinture européenne classique : l'objectivation d'un motif représenté. Selon Jullien, la peinture chinoise vise moins l'objet que l'« évasement » d'une présence qui se retire en se manifestant. Il rapporte ainsi l'anecdote du peintre voulant suggérer la présence d'un temple bouddhique au creux d'un vallon : il ne dessine ni murs ni clochetons, qui figeraient l'atmosphère ; il esquisse seulement, dans l'ombre du chemin, la silhouette d'un moine portant de l'eau, indice détourné qui renvoie au temple sans le borner.<ref>François Jullien, ''De l'Être au Vivre. Lexique euro-chinois de la pensée'', Paris, Gallimard, coll. « Bibliothèque des idées », 2015, p. 374. L'anecdote est également discutée par Jullien dans ''La Grande Image n'a pas de forme. Ou du non-objet par la peinture'', Paris, Seuil, coll. « L'Ordre philosophique », 2003, particulièrement chap. I-II.</ref> ==== Du ''xiangwai'' au ''yijing'' ==== La catégorie du ''yijing'' (意境, généralement rendue par « monde poétique » ou « sphère esthétique ») prolonge celle du ''xiangwai'' dans la critique poétique, en y intégrant la dimension subjective. Une de ses premières formulations remonte au traité ''Shige'' (詩格, ''Normes de poésie'') attribué à Wang Changling (王昌齡, vers 690-756), qui distinguait trois sphères : celle des choses (物境, ''wujing''), celle du sentiment (情境, ''qingjing'') et celle proprement poétique (意境, ''yijing'').<ref>L'attribution à Wang Changling est elle-même discutée. Voir Stephen Owen, ''Readings in Chinese Literary Thought'', Cambridge (Mass.), Harvard University Asia Center, 1992, p. 311-313.</ref> Mais la catégorie ne prend son ampleur théorique qu'au début du XX{{e}} siècle, dans les ''Renjian cihua'' (人間詞話, ''Propos sur les ''ci'' parmi les humains'') de Wang Guowei (王國維, 1877-1927). Wang Guowei systématise ''jingjie'' (境界), terme proche de ''yijing'', comme critère central de l'évaluation poétique : un poème vaut par la sphère qu'il ouvre, sphère qui suppose à la fois la justesse de la notation extérieure et l'authenticité du sentiment intérieur. La catégorie devient ensuite, dans l'esthétique chinoise du XX{{e}} siècle, l'un des concepts ressource pour penser à frais nouveaux la spécificité de l'art chinois, notamment chez Zong Baihua (宗白華, 1897-1986) et chez Li Zehou notamment.<ref>Sur la centralité du ''jingjie'' chez Wang Guowei et sa fortune au XX{{e}} siècle, voir Xia Kejun, « Mountains and Waters », op. cit., qui mobilise la catégorie pour relire Wang Wei et la peinture de paysage. Sur Wang Guowei lui-même, Joey Bonner, ''Wang Kuo-wei: An Intellectual Biography'', Cambridge (Mass.), Harvard University Press, 1986.</ref> Yan Yu (嚴羽, actif vers 1200), dans son ''Canglang shihua'' (滄浪詩話, ''Propos sur la poésie de Canglang''), avait proposé pour caractériser cette dimension « illusoire » mais effective une série d'images qui sont devenues canoniques dans la critique chinoise : la poésie idéale est comparable au « son dans l'air, à la couleur dans la forme, à la lune dans l'eau, au reflet dans le miroir », selon la formule chinoise ''linglong buke coubo'' (玲瓏不可湊泊), cristalline et insaisissable. La poésie ainsi conçue n'est pas allégorie ni symbole, mais éveil d'une dimension que la dénotation ne contient pas et que l'allusion seule peut effleurer.<ref>Yan Yu, ''Canglang shihua'', traduit dans Owen, ''Readings in Chinese Literary Thought'', op. cit., p. 391-420. Sur la lecture de Yan Yu par la tradition Qing, voir aussi Li Zehou, ''The Chinese Aesthetic Tradition'', op. cit., p. 176-178.</ref> ==== Évasif et allusif : la lecture de Jullien ==== François Jullien, dans son ''Lexique euro-chinois'', propose la catégorie d'« évasif » pour désigner ce que les sinologues lui paraissent avoir manqué en cherchant à traduire ''xiangwai'' par des notions occidentales d'idéalité ou de transcendance. L'évasif n'est ni un en-deçà ni un au-delà du sensible : il est ce qui, dans le sensible même, se retire au moment de se déployer. Le paysage chinois, dans sa double dimension de corps (concrétions de souffle) et d'esprit (déploiement de ce même souffle), constitue le paradigme de cette pensée. La poétique de Sikong Tu, avec sa formule « ne pas dire nommément un seul mot, atteindre complètement vents et flots » (不著一字,盡得風流, ''bu zhuo yi zi, jin de fengliu''), en donne l'équivalent littéraire : la parole atteint sa cible non en la nommant mais en la laissant émaner. Jullien rapproche cette logique des « paroles au gré » (卮言, ''zhiyan'') du ''Zhuangzi'', à l'image du vase rituel qui s'incline une fois plein et se redresse une fois vidé.<ref>Jullien, ''De l'Être au Vivre'', op. cit., p. 369-374.</ref> Cette lecture, qui prend ''xiangwai'' comme l'un des opérateurs majeurs d'une pensée du « non-objet », est elle-même située : elle relève d'un effort philosophique contemporain pour repenser l'esthétique européenne par le détour de la Chine, et le rapport qu'elle établit entre catégories chinoises et catégories contemporaines doit être tenu comme une proposition critique et non comme une restitution neutre de la tradition classique. ==== Postérité ==== Les trois catégories examinées (Six Principes, ''chuanshen'', ''xiangwai'') n'épuisent pas le vocabulaire critique de la peinture chinoise, qui inclut encore ''yi'' (逸, le détaché, le libre), ''dan'' (淡, le fade, le limpide), ''xu'' (虛, le vide), et bien d'autres. Mais elles fournissent l'ossature de la plupart des théories postérieures, dans le champ pictural comme dans la poésie et la calligraphie. Leur histoire est faite d'extensions, de déplacements et de reformulations, plus que d'une transmission stabilisée : c'est aussi pour cette raison que les expressions modernes de « synthèse confucéo-taoïste-bouddhiste » ou de « système esthétique chinois » doivent être maniées avec précaution. Les sources premières ne se présentent pas comme un système, et l'élaboration systématique relève pour l'essentiel de la critique des Song et plus encore de la sinologie moderne, occidentale et chinoise, qui a fait des Six Principes, du ''chuanshen'' et du ''xiangwai'' les pierres angulaires d'une tradition rétrospectivement unifiée. == Esthétique et pratiques artistiques == === La calligraphie comme art spirituel (書法, ''shufa'') === [[Fichier:LantingXu.jpg|thumb|right|300px|''Préface du Pavillon des Orchidées'' de Wang Xizhi (321-379), chef-d'œuvre de la calligraphie chinoise]] La calligraphie (書法, ''shufa'', littéralement « méthode de l'écriture ») occupe une place unique et centrale dans l'esthétique chinoise. Considérée depuis des millénaires comme le plus noble des arts, elle transcende la simple fonction utilitaire d'écriture pour devenir une expression spirituelle profonde, une « peinture du cœur » (心畫, ''xinhua'') qui révèle la personnalité, la cultivation morale et l'état intérieur du calligraphe. Cet art constitue une synthèse remarquable des traditions confucéenne, taoïste et bouddhiste, intégrant discipline technique, spontanéité naturelle et révélation spirituelle. ==== La calligraphie comme peinture du cœur (心畫, ''xinhua'') ==== '''La révélation de la personnalité''' : La théorie fondamentale de la calligraphie chinoise affirme que « la calligraphie reflète la personnalité du calligraphe » (書如其人, ''shu ru qi ren'').<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 32.</ref> Cette conception ne voit pas l'écriture comme une simple technique de représentation des caractères, mais comme une manifestation directe de l'esprit et du caractère du calligraphe. Liu Xizai (劉熙載, 1813-1881) affirme dans son traité ''Yigai'' (藝概, ''Visions générales sur l'art'') : « Les bonnes œuvres de calligraphie sont celles qui peuvent entrer dans le royaume de l'esprit (入神, ''ru shen''). Si l'on peut obtenir l'esprit des maîtres anciens, alors on devient comme les maîtres anciens ; si l'on peut exprimer sa propre particularité en plus de cela, alors on peut employer l'ingéniosité des maîtres anciens pour soi-même ».<ref>Liu Xizai, ''Yigai'', Shanghai Classics Publishing House, 1978, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 32.</ref> Cette affirmation établit la double dimension de la maîtrise calligraphique : d'une part, l'assimilation profonde de la tradition à travers l'étude et la copie des anciens maîtres ; d'autre part, l'expression de sa propre personnalité unique à travers le développement d'un style personnel.<ref>Li Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, University of Hawaii Press, p. 120-125.</ref> '''La calligraphie et la peinture : une origine commune''' : Le dicton célèbre « la calligraphie et la peinture ont la même origine » (書畫同源, ''shuhua tongyuan'') établit l'unité fondamentale entre ces deux arts. Tous deux emploient le pinceau, l'encre, le papier et partagent des principes esthétiques communs, notamment les notions de ''qi'' (氣, souffle vital), de ''yun'' (韻, résonnance) et de ''shen'' (神, esprit).<ref>Susan Bush et Hsio-yen Shih (1985). ''Early Chinese Texts on Painting'', Harvard University Press, p. 42-45.</ref> Cependant, la calligraphie est souvent considérée comme supérieure à la peinture car elle manifeste plus directement l'esprit du créateur, sans la médiation d'une représentation figurative. Comme l'affirme un théoricien : « La calligraphie, c'est la peinture sans image » (書者,無象之畫, ''shu zhe, wuxiang zhi hua'').<ref>Cité dans Li Zehou (2010), p. 125.</ref> ==== Les fondements techniques : le ''gufa yongbi'' ==== '''La méthode structurelle du pinceau''' : Le deuxième principe de Xie He — le ''gufa yongbi'' (骨法用筆, « méthode structurelle du pinceau ») — s'applique pleinement à la calligraphie. Cette notion affirme que le trait de pinceau doit posséder une « ossature » (骨, ''gu''), c'est-à-dire une structure solide et une force interne comparable au squelette qui soutient le corps humain.<ref>Bush et Shih (1985), p. 15-17.</ref> Jing Hao (荊浩, actif vers 870-930), dans son ''Bifa ji'' (筆法記, ''Notes sur la méthode du pinceau''), formule cette exigence avec clarté : « Le pinceau possède quatre qualités : la force (筋, ''jin''), la chair (肉, ''rou''), les os (骨, ''gu'') et la vigueur (氣, ''qi''). Si le trait manque d'os, il sera mou comme de la boue ; s'il manque de chair, il sera sec comme du bois mort ».<ref>Jing Hao, ''Bifa ji'', cité dans Bush et Shih (1985), p. 144-148.</ref> Cette métaphore anatomique établit que la calligraphie, comme le corps humain, nécessite à la fois une structure solide (les os), une substance (la chair), une vitalité (la force) et un souffle animateur (le ''qi''). Un trait qui ne possède que la structure sans substance sera dur et sec ; un trait qui possède la substance sans structure sera flasque et sans forme.<ref>Li Zehou (2010), p. 125-130.</ref> '''Les cinq qualités du trait''' : La théorie calligraphique identifie cinq qualités essentielles du trait : * La force (力, ''li'') : le trait doit manifester une puissance interne, comme si le pinceau pénétrait dans le papier « comme une lame tranchant à travers » (入木三分, ''ru mu san fen''). * La rondeur (圓, ''yuan'') : le trait ne doit pas être anguleux et rigide, mais manifester une souplesse et une fluidité. * La légèreté (輕, ''qing'') : paradoxalement, malgré sa force, le trait doit sembler sans effort, comme s'il flottait sur le papier. * La vivacité (活, ''huo'') : le trait doit paraître vivant, animé par un souffle intérieur. * La variété (變, ''bian'') : les traits doivent manifester une richesse de variations, évitant la monotonie.<ref>Discussion dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 176-177.</ref> ==== Les styles calligraphiques et leur évolution ==== '''Les cinq styles canoniques''' : La calligraphie chinoise s'est développée à travers cinq styles principaux, chacun manifestant des qualités esthétiques distinctes : * Le style sigillaire (篆書, ''zhuanshu'') : le plus ancien, caractérisé par des formes arrondies et équilibrées, évoquant la solidité et l'antiquité. * Le style des scribes (隸書, ''lishu'') : développé sous la dynastie Han, plus anguleux et pratique, manifestant une élégance sobre. * Le style régulier (楷書, ''kaishu'') : la forme standard établie sous les dynasties Wei et Jin, caractérisée par sa clarté et sa régularité. * Le style semi-cursif (行書, ''xingshu'') : plus fluide que le style régulier, permettant une expression plus spontanée tout en maintenant la lisibilité. * Le style cursif (草書, ''caoshu'') : le plus libre et le plus expressif, où les caractères se lient et se transforment dans un flux continu d'énergie.<ref>Li Zehou (2010), p. 130-135.</ref> '''Wang Xizhi et l'apogée classique''' : Wang Xizhi (王羲之, 303-361), de la dynastie Jin orientale, est universellement reconnu comme le « Saint de la Calligraphie » (書聖, ''shusheng''). Son œuvre maîtresse, la ''Préface au Pavillon des Orchidées'' (蘭亭序, ''Lanting xu''), est considérée comme le sommet de l'art calligraphique chinois.<ref>Bush et Shih (1985), p. 42-48.</ref> Zhang Huaiguan (張懷瓘, dynastie Tang), dans son traité ''Shuyi'' (書議, ''Discussion sur la calligraphie''), analyse le style de Wang Xizhi et note sa capacité à imprégner chaque marque du pinceau de but et à transmettre un sens de transcendance. Il affirme : « L'essence sublime de la calligraphie émerge à travers le sans-forme et l'intangible. Le ''miao'' (妙, la merveille) est imprévisible et provient de manifestations externes tout en se cachant dans les lacunes entre les choses ».<ref>Zhang Huaiguan, ''Shuyi'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 177.</ref> ==== La cultivation morale et la calligraphie ==== '''Le lien entre vertu et beauté calligraphique''' : La tradition confucéenne établit un lien direct entre la cultivation morale du calligraphe et la qualité de son œuvre. Zhang Yanyuan affirme : « La transmission de l'esprit repose sur la bonne conduite morale, et la bonne conduite morale harmonise la résonnance spirituelle. Ainsi, dans l'antiquité, ceux qui excellaient dans la calligraphie étaient aussi ceux qui pratiquaient la cultivation intérieure ».<ref>Zhang Yanyuan, ''Lidai minghua ji'', cité dans Bush et Shih (1985), p. 53-54.</ref> Cette conception affirme qu'un calligraphe dont le caractère moral est déficient ne pourra jamais atteindre le niveau suprême, quelle que soit sa compétence technique. La beauté calligraphique authentique émane d'un esprit cultivé, d'un cœur purifié et d'une personnalité noble.<ref>Li Zehou (2010), p. 140-145.</ref> '''Le ''fenggu'' en calligraphie''' : Le concept de ''fenggu'' (風骨, « intégrité morale ») s'applique pleinement à la calligraphie. Comme l'explique le ''Zhenyi zhai shishuo'' (真意齋詩說, ''Paroles sur la poésie du Studio de la vraie intention'') de Li Chonghua (dynastie Qing) : « La manière (風, ''feng'') est contenue dans l'esprit (神, ''shen''), les os (骨, ''gu'') sont fournis par le ''qi'' (氣, souffle vital), et la manière et les os sont inextricablement liés à l'esprit et au souffle vital ».<ref>Li Chonghua, ''Zhenyi zhai shishuo'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 90.</ref> Zhang Huaiguan, dans son ''Shuyi'', utilise ensemble les termes ''fengshen'' (風神, manière et esprit) et ''guqi'' (骨氣, os et souffle vital), qu'il considère comme supérieurs à la simple technique.<ref>Zhang Huaiguan, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 90.</ref> ==== La spontanéité et le non-agir en calligraphie ==== '''L'influence taoïste''' : La tradition taoïste apporte à la calligraphie l'idéal de spontanéité (自然, ''ziran'') et de non-agir (無為, ''wuwei''). La calligraphie la plus accomplie ne doit révéler aucune trace d'effort ou de calcul, mais doit émaner naturellement, comme l'eau coulant d'une source.<ref>François Jullien (2004). ''De l'Être au Vivre : Lexique euro-chinois de la pensée'', Gallimard, p. 375-380.</ref> Xiang Mu (項穆, 1550-1600) affirme dans son ''Shufa yayan'' (書法雅言, ''Paroles élégantes sur la calligraphie'') : « Bien qu'il y ait des méthodes à apprendre, la beauté réside dans ce qui est sans effort » (雖有法可學,妙在無意, ''sui you fa ke xue, miao zai wuyi'').<ref>Xiang Mu, ''Shufa yayan'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 178.</ref> Cette formulation condense le paradoxe central de la calligraphie : bien que la maîtrise technique nécessite des années d'apprentissage rigoureux, l'accomplissement ultime requiert l'oubli de toute technique, permettant au pinceau de se mouvoir spontanément, guidé par l'esprit plutôt que par la volonté consciente.<ref>Li Zehou (2010), p. 145-150.</ref> '''La calligraphie cursive comme expression de la liberté''' : Le style cursif (草書, ''caoshu'') incarne particulièrement cet idéal de spontanéité. Dans ce style, les caractères se lient en un flux continu, le pinceau ne quittant presque jamais le papier, créant ce qu'on appelle la « calligraphie folle » (狂草, ''kuangcao'').<ref>Bush et Shih (1985), p. 155-160.</ref> Zhang Xu (張旭, actif vers 700-750) et Huaisu (懷素, 737-799), maîtres du style cursif de la dynastie Tang, sont célèbres pour leurs œuvres d'une spontanéité et d'une liberté extrêmes. On raconte que Zhang Xu écrivait dans un état d'ivresse, le pinceau dansant sur le papier comme un tourbillon.<ref>Li Zehou (2010), p. 150-155.</ref> ==== Le vide et la plénitude en calligraphie ==== '''L'espace blanc comme élément constitutif''' : La calligraphie chinoise accorde une importance capitale à l'espace blanc (blanc, ''bai'' ou vide, ''xu''), considéré non comme une absence mais comme un élément actif de la composition. Comme l'affirme le proverbe : « Estimer le vide comme le plein » (計白當黑, ''ji bai dang hei'', littéralement « calculer le blanc comme le noir »).<ref>Zong Baihua (1986). ''Se promener dans l'esthétique'' (美學散步, ''Meixue Sanbu''), Shanghai Peoples Publishing House, p. 33-34, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164.</ref> Le philosophe Xiong Bingming (熊秉明, 1922-2002) compare les œuvres de deux célèbres calligraphes pour illustrer cette dimension : « Les traits de Yan Zhenqing (顏真卿, 709-785) sont épais et solides, avec des structures complexes étroitement tissées entre les mots et les lignes, et l'existence domine tandis que la non-existence est supprimée. En revanche, dans l'œuvre de Chu Suiliang (褚遂良, 596-658), l'existence et la non-existence coexistent et se pénètrent mutuellement, ce qui crée un espace vaste et tranquille ».<ref>Xiong Bingming, ''A Systematic Review of Chinese Calligraphy Theories'', Commercial Press Hong Kong, 1984, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164.</ref> '''Le rythme et le souffle''' : La calligraphie chinoise est fondamentalement rythmique, manifestant ce qu'on appelle le « souffle-rythme » (氣韻, ''qiyun''). Le calligraphe, comme le musicien, doit maîtriser les alternances de vitesse et de lenteur, de pression et de légèreté, de plein et de vide, créant une composition dynamique qui respire et pulse.<ref>Jullien (2004), p. 380-385.</ref> Yu Shinan (虞世南, 558-638), dans son traité ''Bisui lun'' (筆髓論, ''Sur l'essence de la calligraphie''), comprend une section intitulée « Sculpter la subtilité » (琦妙, ''Qi Miao''), qui affirme que « le Dao de la calligraphie réside dans le royaume de la subtilité mystérieuse/profondeur (玄妙, ''xuanmiao''), qui ne peut être atteint que par un dévouement concentré et une compréhension profonde des subtilités de l'artisanat ».<ref>Yu Shinan, ''Bisui lun'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 176.</ref> ==== Les trois catégories de l'excellence calligraphique ==== '''Zhang Huaiguan et la classification tripartite''' : Zhang Huaiguan (張懷瓘) établit une hiérarchie tripartite des œuvres calligraphiques de première classe : * Les œuvres divines (神品, ''shenpin'') : le niveau suprême, où la calligraphie transcende toute technique pour atteindre le royaume de l'esprit pur. * Les œuvres profondes (妙品, ''miaopin'') : le niveau de la subtilité merveilleuse, où la technique parfaite se combine à une profondeur spirituelle. * Les œuvres habiles (能品, ''nengpin'') : le niveau de la maîtrise technique, où l'artisan a acquis une compétence complète mais n'a pas encore atteint la dimension spirituelle.<ref>Zhang Huaiguan, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 176.</ref> Zhang élabore sur les œuvres profondes (''miaopin'') : « Les chefs-d'œuvre profonds en calligraphie et en littérature doivent contenir des implications profondes. Les idées profondes (玄妙, ''xuanmiao'') ne sont pas dérivées de la surface des sujets mais d'une source plus profonde. Comment pourrait-on l'expliquer ou le prédire par la rationalité commune ou la connaissance mondaine ? Seuls ceux qui possèdent une perspicacité et une vision exceptionnelles peuvent apprécier la profondeur des éléments sans son et sans forme ».<ref>Zhang Huaiguan, ''Shuyi'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 176-177.</ref> '''L'importance de l'observation spirituelle''' : Zhang souligne que « seuls ceux qui possèdent une compréhension profonde de la calligraphie peuvent observer l'esprit divin de l'artisanat et regarder au-delà des traits et des caractères eux-mêmes... même si l'écriture est rangée, l'âme suit toujours et le cœur la chérit, c'est le ''miao'' (妙, la merveille) ».<ref>Zhang Huaiguan, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 177.</ref> Cette affirmation établit que l'appréciation calligraphique authentique dépasse la simple évaluation technique pour atteindre une communion spirituelle avec l'œuvre et, à travers elle, avec l'esprit du calligraphe.<ref>Li Zehou (2010), p. 155-160.</ref> ==== Synthèse : la calligraphie comme voie spirituelle ==== La calligraphie chinoise (書法, ''shufa'') représente bien plus qu'un art de l'écriture. Elle constitue une voie spirituelle (道, ''dao'') complète qui : * Manifeste directement la personnalité, le caractère et l'état intérieur du calligraphe * Intègre discipline technique rigoureuse et spontanéité naturelle * Requiert cultivation morale et purification spirituelle * Valorise la structure solide (骨, ''gu'') tout en maintenant la souplesse et la fluidité * Accorde une importance égale au plein et au vide, au trait et à l'espace blanc * Transcende la simple technique pour atteindre le royaume de l'esprit (神, ''shen'') Cette conception holistique fait de la calligraphie « le premier des arts » dans la tradition chinoise, synthétisant toutes les dimensions de l'esthétique chinoise : confucéenne (par l'accent sur la moralité), taoïste (par la valorisation de la spontanéité) et bouddhiste (par la transcendance du moi). La calligraphie demeure ainsi un art vivant qui continue d'incarner les valeurs spirituelles les plus profondes de la civilisation chinoise. === La peinture de lettrés (文人畫, ''wenrenhua'') === La peinture de lettrés (文人畫, ''wenrenhua'', littéralement « peinture d'hommes de lettres ») représente l'une des traditions artistiques les plus distinctives et les plus influentes de la Chine. Émergeant pleinement sous la dynastie Song (宋, 960-1279) et s'épanouissant sous les Yuan, Ming et Qing, cette forme d'art privilégie l'expression personnelle, la cultivation spirituelle et la spontanéité créatrice sur la virtuosité technique et la ressemblance mimétique. Elle incarne une synthèse remarquable entre calligraphie, poésie et peinture, où l'artiste-lettré exprime son intériorité morale et esthétique à travers le pinceau et l'encre. ==== Les origines et le contexte historique ==== '''Su Shi et la révolution esthétique''' : Su Shi (蘇軾, 1037-1101), également connu sous le nom de Su Dongpo, joua un rôle décisif dans la formation de l'esthétique de la peinture de lettrés. Poète, calligraphe, peintre et homme d'État accompli, Su Shi articula une théorie esthétique qui valorisait l'expression de l'intention intérieure (意, ''yi'') sur la reproduction de l'apparence extérieure.<ref>Li Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, University of Hawaii Press, p. 160-165.</ref> Dans ses ''Notes sur la salle des trésors picturaux'' (寶繪堂記, ''Baohuitang Ji''), Su Shi formula la méthode esthétique de « l'intention dans les choses plutôt que l'attention aux choses » (意在物而不留於物, ''yi zai wu er bu liu yu wu''). Cette méthode signifie placer son esprit dans les choses, apprécier leur signification et leur rythme, mais sans s'y attacher obstinément.<ref>Su Shi, ''Baohuitang Ji'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 383-384.</ref> Su Shi critiqua également l'obsession de la ressemblance formelle, affirmant : « Discuter la peinture en termes de ressemblance formelle révèle une compréhension qui n'est pas différente de celle des enfants » (論畫以形似,見與兒童鄰, ''lun hua yi xingsi, jian yu ertong lin'').<ref>Su Shi, cité dans Li Zehou (2010), p. 162.</ref> '''L'idéal de l'amateur cultivé''' : La peinture de lettrés se distingue fondamentalement de la peinture professionnelle (工筆畫, ''gongbihua'' ou peinture minutieuse). Alors que les peintres professionnels, souvent employés par la cour ou travaillant pour des commandes, privilégiaient la technique virtuose et la représentation détaillée, les lettrés-peintres valorisaient l'expression spontanée de leur cultivation intérieure et de leur personnalité.<ref>Susan Bush et Hsio-yen Shih (1985). ''Early Chinese Texts on Painting'', Harvard University Press, p. 180-185.</ref> Cette distinction n'impliquait pas un mépris de la technique, mais plutôt une hiérarchie où la technique devait servir l'expression spirituelle plutôt que devenir une fin en soi. Comme l'affirme Dong Qichang (董其昌, 1555-1636) : « Dans la peinture, il y a les écoles du Sud et du Nord, comme dans le bouddhisme Chan il y a les écoles du Sud et du Nord. L'école du Nord privilégie la technique minutieuse et les couleurs éclatantes ; l'école du Sud valorise l'encre libre et la spontanéité ».<ref>Dong Qichang, cité dans Bush et Shih (1985), p. 275-280.</ref> ==== Les thèmes privilégiés : les Quatre Gentilshommes ==== '''Les plantes symboliques''' : La peinture de lettrés développa un corpus de thèmes privilégiés, notamment les « Quatre Gentilshommes » (四君子, ''si junzi'') : le prunier (梅, ''mei''), l'orchidée (蘭, ''lan''), le bambou (竹, ''zhu'') et le chrysanthème (菊, ''ju''). Ces quatre plantes incarnent des qualités morales confucéennes que l'homme de bien doit cultiver.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 85-88.</ref> * Le prunier (梅, ''mei'') : fleurissant au cœur de l'hiver, il symbolise la persévérance, la pureté et la capacité à prospérer dans l'adversité. * L'orchidée (蘭, ''lan'') : poussant dans les vallées reculées, elle incarne l'humilité, l'élégance et le refus de la renommée mondaine. * Le bambou (竹, ''zhu'') : restant vert toute l'année et flexible mais jamais brisé, il représente l'intégrité, la droiture et la résilience. * Le chrysanthème (菊, ''ju'') : fleurissant à l'automne après le départ des autres fleurs, il symbolise la noblesse dans la solitude et le détachement des honneurs.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 85-88.</ref> '''La peinture de bambou''' : La peinture de bambou (墨竹, ''mozhu'', « bambou à l'encre ») occupe une place particulièrement importante dans la tradition des lettrés. Wen Tong (文同, 1018-1079), maître de ce genre, et son ami Su Shi développèrent une approche qui valorisait l'expression de l'essence spirituelle du bambou plutôt que sa représentation détaillée.<ref>Li Zehou (2010), p. 165-170.</ref> Su Shi expliqua la méthode de Wen Tong : « Lorsque Yuke (Wen Tong) peint le bambou, il doit d'abord avoir le bambou complet dans son esprit (胸有成竹, ''xiong you cheng zhu''). Puis, tenant le pinceau et fixant du regard, il voit ce qu'il veut peindre. Il se lève alors rapidement et le poursuit avec son pinceau, craignant de le perdre comme un lièvre qui surgit devant un faucon ».<ref>Su Shi, cité dans Li Zehou (2010), p. 167.</ref> Cette méthode exige que le peintre intériorise d'abord profondément l'essence du bambou à travers l'observation et la méditation, puis l'exécute spontanément, sans hésitation ni calcul, dans un état de fusion entre le sujet et l'objet.<ref>Bush et Shih (1985), p. 185-190.</ref> ==== L'encre monochrome et la peinture de paysage ==== '''Le triomphe de l'encre sur la couleur''' : La peinture de lettrés privilégia progressivement la peinture à l'encre monochrome (水墨畫, ''shuimo hua'') sur la peinture polychrome traditionnelle. Cette préférence s'enracinait dans la conception que l'encre, étant la « couleur mère » (母色, ''mu se''), possède un potentiel expressif infini.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164-165.</ref> Wang Wei (王維, 699-759), considéré comme l'un des fondateurs de la peinture de paysage à l'encre, affirma : « Dans l'art de la peinture, l'encre de lavis est la plus supérieure. Elle capture naturellement l'essence et crée l'univers » (畫道之中,水墨最為上,肇自然之性,成造化之功, ''huadao zhi zhong, shuimo zui wei shang, zhao ziran zhi xing, cheng zaohua zhi gong'').<ref>Wang Wei, ''Shanshui Jue'' (山水訣, ''Tips on Landscape Painting''), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 179.</ref> Zhang Yanyuan (張彥遠, vers 815-877) développa davantage cette théorie dans son ''Lidai minghua ji'' (歷代名畫記, ''Registre des peintures célèbres de toutes les dynasties'') : « Les herbes et les arbres fleurissent sans avoir besoin d'utiliser le rouge ; la neige et les nuages flottent sans avoir besoin d'utiliser le blanc ; les montagnes n'ont pas besoin de bleu vide pour être vertes, et les phénix n'ont pas besoin de cinq couleurs pour être astucieux. Par conséquent, lorsque l'encre est utilisée et que les cinq couleurs sont présentes, on dit que c'est réussi ».<ref>Zhang Yanyuan, ''Lidai minghua ji'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 179-180.</ref> '''La peinture de paysage comme expression spirituelle''' : Guo Xi (郭熙, 1020-1090), dans son traité ''Linquan gaozhi'' (林泉高致, ''Le Message sublime des forêts et des sources''), articula une théorie élaborée de la peinture de paysage qui intégrait dimensions technique, spirituelle et morale.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 178, 182-183.</ref> Il décrivit comment les peintures de paysage créent des expériences immersives : « Dans les peintures, les routes couvertes par les brumes matinales rappellent aux spectateurs qu'ils sont des passants matinaux ; le soleil couchant à l'horizon fait penser aux spectateurs à regarder le coucher de soleil ; les habitants des montagnes donnent aux spectateurs l'impression d'y habiter ; et les falaises, les rochers et les sources attirent les spectateurs à voyager. Voir des peintures fait penser à certaines choses et fait sentir comme si on était littéralement là dans la scène. C'est le mystère surprenant (妙, ''miao'') des peintures ».<ref>Guo Xi, ''Linquan gaozhi'', chapitre « Lessons from the Mountains and Waters », cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 178.</ref> ==== Dong Qichang et la théorie des écoles du Sud et du Nord ==== '''La classification théorique''' : Dong Qichang (董其昌, 1555-1636), peintre, calligraphe et théoricien de la dynastie Ming, formula une distinction influente entre l'« école du Sud » (南宗, ''nanzong'') et l'« école du Nord » (北宗, ''beizong'') en peinture, analogie empruntée à la division du bouddhisme Chan entre l'école du Sud (illumination subite) et l'école du Nord (illumination graduelle).<ref>Dong Qichang, cité dans Bush et Shih (1985), p. 275-280.</ref> Selon Dong, l'école du Nord, représentée par des peintres professionnels et de cour, privilégiait la technique minutieuse (工筆, ''gongbi''), les couleurs éclatantes et la représentation détaillée. L'école du Sud, incarnée par les lettrés-peintres, valorisait l'expression spontanée (寫意, ''xieyi'', « écrire l'intention »), l'encre monochrome et la suggestion évocatrice.<ref>Li Zehou (2010), p. 170-175.</ref> Dans ses ''Esquisses à l'Atelier de l'Art-Zen'' (畫禪室隨筆, ''Hua Chan Shi Suibi''), Dong affirma : « Il est nécessaire de distinguer entre le réel et l'imaginaire. Le réel est le travail de pinceau détaillé dans chaque partie. Où certaines parties sont détaillées, d'autres doivent être brèves. L'usage du réel et de l'imaginaire doit s'équilibrer... seulement alors il peut y avoir une œuvre extraordinaire ».<ref>Dong Qichang, ''Hua Chan Shi Suibi'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164.</ref> '''Le vide et le plein''' : Dong Qichang et les peintres lettrés accordèrent une importance capitale à la technique de « laisser le blanc » (留白, ''liu bai''), créant des espaces vides qui suggèrent l'infini et invitent l'imagination du spectateur.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 163-164.</ref> Comme le note le philosophe Zong Baihua (宗白華, 1897-1986) : « Les peintres chinois soulignent l'importance de l'espace blanc. Par exemple, Ma Yuan était connu comme "Ma Yijiao" (Ma-un-coin) parce qu'il peignait souvent seulement un coin, laissant le reste blanc. Mais l'espace blanc ne semble pas vide parce qu'il est rempli de mer et de ciel. L'espace blanc est plus riche en images que s'il était rempli de traits de pinceau ».<ref>Zong Baihua (1986). ''Se promener dans l'esthétique'' (美學散步, ''Meixue Sanbu''), Shanghai Peoples Publishing House, p. 33-34, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164.</ref> ==== L'intégration des Trois Perfections ==== '''Poésie, calligraphie et peinture''' : La peinture de lettrés se distingue par l'intégration harmonieuse des « Trois Perfections » (三絕, ''san jue'') : la poésie (詩, ''shi''), la calligraphie (書, ''shu'') et la peinture (畫, ''hua''). Cette synthèse transforme l'œuvre picturale en un espace multidimensionnel où texte et image dialoguent et se complètent.<ref>Li Zehou (2010), p. 175-180.</ref> Les peintres lettrés inscrivaient souvent des poèmes directement sur leurs peintures, créant une composition unifiée où l'écriture calligraphique ne se contente pas de commenter l'image, mais participe à sa structure visuelle et à sa signification spirituelle. Les sceaux (印章, ''yinzhang'') ajoutaient une dimension supplémentaire, créant des points d'accent rouge qui équilibrent la composition.<ref>Bush et Shih (1985), p. 285-290.</ref> '''La spontanéité comme idéal''' : L'idéal esthétique de la peinture de lettrés valorise la spontanéité (自然, ''ziran'') et l'absence d'artifice. Comme Xiang Mu (項穆, 1550-1600) l'affirme : « Bien qu'il y ait des méthodes à apprendre, la beauté réside dans ce qui est sans effort » (雖有法可學,妙在無意, ''sui you fa ke xue, miao zai wuyi'').<ref>Xiang Mu, ''Shufa Yayan'' (書法雅言, ''Elegant Words on Calligraphy''), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 178.</ref> Cette spontanéité, loin d'être une improvisation naïve, résulte de longues années de cultivation technique et spirituelle qui permettent au pinceau de se mouvoir librement, sans entrave de la volonté consciente.<ref>Li Zehou (2010), p. 180-185.</ref> ==== Les maîtres de la tradition lettré ==== '''Les Quatre Maîtres Yuan''' : Sous la dynastie Yuan (元, 1271-1368), quatre peintres incarnèrent l'apogée de la peinture de lettrés : Huang Gongwang (黃公望, 1269-1354), Wu Zhen (吳鎮, 1280-1354), Ni Zan (倪瓚, 1301-1374) et Wang Meng (王蒙, 1308-1385). Refusant de servir les conquérants mongols, ils se retirèrent dans la vie privée et exprimèrent leur intégrité morale à travers la peinture.<ref>Bush et Shih (1985), p. 240-250.</ref> Ni Zan, en particulier, développa un style d'une simplicité et d'une sobriété extrêmes, caractérisé par des paysages dépouillés à l'encre sèche qui expriment un sentiment de solitude et de détachement. Il affirmait : « Ce que je peins n'est pas la ressemblance des choses, mais simplement pour exprimer l'évasion de mon cœur ».<ref>Ni Zan, cité dans Li Zehou (2010), p. 182.</ref> '''Les individualistes de la fin des Ming''' : À la chute de la dynastie Ming et au début des Qing, plusieurs peintres « individualistes » ou « excentriques » radicalisèrent l'esthétique lettré. Bada Shanren (八大山人, 1626-1705), prince Ming devenu moine bouddhiste après la conquête mandchoue, créa des œuvres d'une expressivité extrême, caractérisées par des formes simplifiées et des compositions audacieuses qui expriment une douleur et un aliénation profondes.<ref>Bush et Shih (1985), p. 310-320.</ref> ==== Synthèse : la peinture de lettrés comme voie spirituelle ==== La peinture de lettrés (文人畫, ''wenrenhua'') représente bien plus qu'un style pictural. Elle constitue une voie spirituelle complète qui : * Valorise l'expression de l'intention intérieure (意, ''yi'') sur la reproduction de l'apparence extérieure (形, ''xing'') * Privilégie la cultivation morale et spirituelle sur la virtuosité technique * Intègre harmonieusement poésie, calligraphie et peinture en une synthèse esthétique * Utilise l'encre monochrome pour suggérer l'infini des couleurs * Accorde une importance capitale au vide et à l'espace blanc * Incarne l'idéal de l'amateur cultivé qui peint pour l'expression de soi plutôt que pour la commande * Exprime des qualités morales confucéennes à travers des thèmes symboliques comme les Quatre Gentilshommes Cette tradition continue d'influencer profondément l'art chinois contemporain et représente une alternative remarquable à la tradition occidentale, valorisant la suggestion sur la représentation, l'expression personnelle sur l'objectivité mimétique, et la cultivation spirituelle sur la maîtrise technique. === La poésie et la peinture (詩畫一體, ''shi hua yiti'') === Le principe de l'unité entre poésie et peinture (詩畫一體, ''shi hua yiti'', littéralement « poésie et peinture forment un corps ») représente l'un des concepts esthétiques les plus distinctifs de la tradition chinoise. Cette conception affirme que la poésie et la peinture, bien qu'utilisant des médiums différents — les mots pour la première, l'image pour la seconde — partagent les mêmes principes esthétiques et poursuivent le même but : l'expression de l'intention intérieure (意, ''yi'') et la création d'un royaume artistique (境, ''jing'') où émotion et paysage se fondent harmonieusement. ==== Les fondements théoriques : « Il y a de la peinture dans la poésie » ==== '''Su Shi et la formule célèbre''' : Su Shi (蘇軾, 1037-1101) formula la théorie classique de l'unité entre poésie et peinture dans son évaluation de l'œuvre de Wang Wei (王維, 699-759), poète et peintre de la dynastie Tang. Su Shi écrit : « En appréciant les poèmes de Mojie (Wang Wei), il y a de la peinture dans la poésie ; en regardant les peintures de Mojie, il y a de la poésie dans la peinture » (味摩詰之詩,詩中有畫;觀摩詰之畫,畫中有詩, ''wei Mojie zhi shi, shizhong you hua; guan Mojie zhi hua, huazhong you shi'').<ref>Su Shi, « Sur les peintures de paysage de Wang Mojie » (書摩詰藍田煙雨圖, ''Shu Mojie Lantian Yanyu Tu''), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 383.</ref> Cette formulation ne signifie pas simplement que les poèmes de Wang Wei décrivent des paysages ou que ses peintures racontent des histoires. Elle affirme plutôt que la poésie et la peinture partagent la même essence spirituelle : toutes deux créent un royaume artistique (意境, ''yijing'') où l'intention intérieure du créateur et le paysage extérieur se fondent en une unité organique.<ref>Li Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, University of Hawaii Press, p. 185-190.</ref> '''Wang Wei comme paradigme''' : Wang Wei incarne parfaitement cette synthèse. Comme l'affirme son traité ''Shanshui jue'' (山水訣, ''Conseils sur les montagnes et les eaux'') : « Dans l'art de la peinture, l'encre de lavis est la plus supérieure. Elle capture naturellement l'essence et crée l'univers » (畫道之中,水墨最為上,肇自然之性,成造化之功, ''huadao zhi zhong, shuimo zui wei shang, zhao ziran zhi xing, cheng zaohua zhi gong'').<ref>Wang Wei, ''Shanshui Jue'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 179.</ref> Cette conception place la peinture et la poésie sur le même plan : toutes deux doivent « capturer naturellement l'essence » (肇自然之性, ''zhao ziran zhi xing'') plutôt que reproduire mécaniquement l'apparence extérieure.<ref>Susan Bush et Hsio-yen Shih (1985). ''Early Chinese Texts on Painting'', Harvard University Press, p. 190-195.</ref> ==== Le ''yijing'' : la conception artistique ==== '''La fusion de l'intention et du royaume''' : Le concept de ''yijing'' (意境, « conception artistique » ou « royaume poétique ») constitue le fondement théorique de l'unité entre poésie et peinture. Ce terme, composé de ''yi'' (意, « intention », « signification ») et de ''jing'' (境, « royaume », « scène »), désigne l'unité harmonieuse entre la dimension subjective (l'intention de l'artiste) et la dimension objective (le paysage ou la scène représentée).<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 325-337.</ref> Wang Changling (王昌齡, actif vers 730), dans ses ''Normes de poésie'' (詩格, ''Shige''), fut le premier à introduire le concept de « royaume poétique » (詩境, ''shijing'') et à le diviser en trois catégories : * Le royaume des choses (物境, ''wujing'') : la représentation objective des paysages * Le royaume de l'émotion (情境, ''qingjing'') : l'expression des émotions subjectives * Le royaume poétique (詩境, ''shijing'') : la fusion harmonieuse des deux<ref>Wang Changling, ''Shige'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 328-329.</ref> '''L'évolution du concept''' : Liu Yuxi (劉禹錫, 772-842) affirma : « Le royaume surgit au-delà de l'image » (境生於象外, ''jing sheng yu xiangwai'').<ref>Liu Yuxi, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 329.</ref> Cette formulation établit que le véritable royaume artistique ne se limite pas aux images explicitement représentées ou décrites, mais émerge au-delà d'elles, dans l'espace de suggestion et d'évocation. Sikong Tu (司空圖, 837-908) développa davantage : « Comment peut-on parler facilement de l'image au-delà de l'image et de la scène au-delà de la scène ? » (象外之象,景外之景, ''xiangwai zhi xiang, jingwai zhi jing'').<ref>Sikong Tu, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 329.</ref> ==== La correspondance entre intention et image ==== '''La théorie de Su Shi''' : Su Shi développa une théorie systématique de l'expression artistique fondée sur le principe : « choisir les formes selon les objets » (隨物賦形, ''sui wu fu xing''). Dans son œuvre ''Wen Shuo'' (文說, ''Paroles sur la littérature''), il explique : « Mon écriture est comme une source d'abondance d'eau. Elle coule indifféremment et se précipite à travers le sol plat, couvrant des milliers de lieues en un jour sans difficulté. Cependant, lorsqu'elle rencontre les contours et détours des montagnes et des rochers, elle choisit les formes selon la nature des objets. Ce qui peut être connu, c'est qu'elle se déplace toujours où elle doit se déplacer et s'arrête où elle doit s'arrêter. C'est tout. Quant au reste, je ne peux le savoir ».<ref>Su Shi, ''Wen Shuo'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 143-144.</ref> Cette métaphore de l'eau s'adaptant naturellement aux contours du terrain illustre comment la forme artistique — qu'elle soit poétique ou picturale — doit suivre organiquement le contenu à exprimer, plutôt que d'imposer des structures rigides préétablies.<ref>Li Zehou (2010), p. 190-195.</ref> '''L'harmonie naturelle''' : Su Shi décrit cette adéquation comme « l'harmonie naturelle dans le texte et la forme, avec diverses postures surgissant » (文理自然,姿態橫生, ''wenli ziran, zitai hengsheng'').<ref>Su Shi, ''Da Xie Minshi Shu'' (答謝民師書, ''Réponse à Xie Minshi''), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 145.</ref> Cette conception valorise la diversité des formes artistiques, chacune adaptée à un contenu et une intention spécifiques, contre l'imitation mécanique des formes anciennes.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 145.</ref> ==== La picturalité de la poésie ==== '''Créer des images visuelles par les mots''' : La poésie chinoise vise à créer des images visuelles aussi vivantes que celles d'une peinture. Comme l'affirme un critique : « Quand on écrit sur le paysage, les gens peuvent le voir et l'entendre » (寫景能見能聽, ''xie jing neng jian neng ting'').<ref>Wang Guowei, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 334.</ref> Les grands poètes Tang et Song, notamment Wang Wei, Du Fu (杜甫, 712-770) et Su Shi, excellaient dans la création de tableaux verbaux d'une précision et d'une évocativité remarquables. Les vers de Wang Wei comme « Dans les montagnes vides, personne n'est là, on entend seulement l'écho des voix humaines » (空山不見人,但聞人語響, ''kongshan bu jian ren, dan wen ren yu xiang'') créent un paysage visuel et sonore aussi vivant qu'une peinture.<ref>Li Zehou (2010), p. 195-200.</ref> '''La peinture mentale''' : Guo Xi (郭熙, 1020-1090) explique comment les peintures de paysage créent des expériences immersives qui stimulent l'imagination du spectateur : « Dans les peintures, les routes couvertes par les brumes matinales rappellent aux spectateurs qu'ils sont des passants matinaux ; le soleil couchant à l'horizon fait penser aux spectateurs à regarder le coucher de soleil ; les habitants des montagnes donnent aux spectateurs l'impression d'y habiter ; et les falaises, les rochers et les sources attirent les spectateurs à voyager. Voir des peintures fait penser à certaines choses et fait sentir comme si on était littéralement là dans la scène. C'est le mystère surprenant (妙, ''miao'') des peintures ».<ref>Guo Xi, ''Linquan gaozhi'', chapitre « Leçons des montagnes et des eaux », cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 178.</ref> La même qualité immersive caractérise la grande poésie, transportant le lecteur dans le royaume évoqué.<ref>Bush et Shih (1985), p. 200-205.</ref> ==== La poéticité de la peinture ==== '''L'inscription poétique sur la peinture''' : Une caractéristique distinctive de la peinture chinoise, notamment de la peinture de lettrés, est l'intégration de poèmes calligraphiés directement sur la surface picturale. Cette pratique, qui se développa pleinement sous les Song et s'épanouit sous les Yuan, Ming et Qing, transforme la peinture en un espace multidimensionnel où texte, calligraphie et image dialoguent.<ref>Li Zehou (2010), p. 200-205.</ref> Les inscriptions ne se contentent pas de commenter ou d'expliquer l'image, mais participent à la création du ''yijing'' — le royaume artistique. Le poème inscrit peut amplifier l'émotion suggérée par l'image, introduire une dimension temporelle ou narrative, ou établir une résonance spirituelle qui transcende la représentation visuelle.<ref>Bush et Shih (1985), p. 285-290.</ref> '''La suggestion plutôt que la description''' : Tout comme la poésie chinoise valorise l'allusion (allusif) sur l'explicite, la peinture chinoise privilégie la suggestion sur la description exhaustive. Dong Qichang (董其昌, 1555-1636) affirme : « Il est nécessaire de distinguer entre le réel et l'imaginaire. Le réel est le travail de pinceau détaillé dans chaque partie. Où certaines parties sont détaillées, d'autres doivent être brèves. L'usage du réel et de l'imaginaire doit s'équilibrer... seulement alors il peut y avoir une œuvre extraordinaire ».<ref>Dong Qichang, ''Hua Chan Shi Suibi'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 164.</ref> Cette alternance entre le plein et le vide, entre le détaillé et le suggéré, crée un espace pour l'imagination du spectateur — exactement comme la poésie laisse des espaces non-dits que le lecteur doit remplir.<ref>François Jullien (2003). ''La Grande Image n'a pas de forme'', Seuil, p. 200-210.</ref> ==== Wang Guowei et la théorie du ''jingjie'' ==== '''La synthèse moderne''' : Wang Guowei (王國維, 1877-1927), critique littéraire du début du XXe siècle, systématisa la théorie du ''jingjie'' (境界, « royaume » ou « sphère esthétique ») dans son œuvre ''Renjian cihua'' (人間詞話, ''Remarques sur les paroles dans le monde humain''), créant une synthèse entre esthétique traditionnelle chinoise et concepts occidentaux.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 332-337.</ref> Il affirma : « Que les œuvres littéraires soient bien écrites dépend de si elles ont un royaume et de sa profondeur... Pour la poésie Ci, le royaume est le plus important. Avec lui, les œuvres seront sublimes et les phrases célèbres émergeront ».<ref>Wang Guowei, ''Renjian cihua'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 334.</ref> '''Le royaume avec soi et le royaume sans soi''' : Wang Guowei distingua deux types de royaumes artistiques : * Le royaume avec soi (有我之境, ''you wo zhi jing'') : où le sujet projette ses émotions sur le paysage, colorant tout de ses sentiments. Exemple : « Je demande aux fleurs avec mes yeux remplis de larmes, pourtant les fleurs restent silencieuses, je ne vois rien sauf des pétales volant au-delà de la balançoire ».<ref>Wang Guowei, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 335.</ref> * Le royaume sans soi (無我之境, ''wu wo zhi jing'') : où le sujet contemple le paysage objectivement, sans imposer ses émotions. Exemple : « Comme le chrysanthème est cueilli près de la clôture orientale, je me détends et contemple la montagne méridionale ».<ref>Wang Guowei, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 335.</ref> Wang ne privilégie ni l'un ni l'autre, reconnaissant que les deux approches peuvent créer de grandes œuvres.<ref>Li Zehou (2010), p. 210-215.</ref> ==== La réalité et l'illusion dans le royaume artistique ==== '''Le royaume réel et le royaume illusoire''' : Les critiques chinois distinguent le royaume réel (實境, ''shijing'') du royaume illusoire (虛境, ''xujing''). Le royaume réel correspond aux images et scènes explicitement représentées ou décrites. Le royaume illusoire correspond à ce qui est évoqué au-delà, à « l'image au-delà de l'image » et à « la scène au-delà de la scène ».<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 329-330.</ref> Le véritable accomplissement artistique consiste à « contenir l'illusion dans la réalité et atteindre un royaume et une image infinis à travers un royaume et une image finis » (寓虛於實,以有限達無限, ''yu xu yu shi, yi youxian da wuxian'').<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 329.</ref> '''Les caractéristiques illusoires''' : Yan Yu (嚴羽, actif vers 1180-1235) exige que les poèmes merveilleux soient « cristallins et clairs, inaccessibles, tout comme le son dans l'air, la couleur dans la forme, la lune dans l'eau, et le reflet dans le miroir ».<ref>Yan Yu, ''Canglang shihua'', cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 330.</ref> Ces métaphores — le son dans l'air, la lune dans l'eau, le reflet dans le miroir — capturent parfaitement la nature illusoire et insaisissable du royaume artistique créé par la grande poésie et la grande peinture. Elles existent réellement dans l'expérience du lecteur ou du spectateur, mais ne peuvent être saisies matériellement.<ref>Jullien (2003), p. 215-220.</ref> ==== Synthèse : l'unité fondamentale des arts ==== Le principe de l'unité entre poésie et peinture (詩畫一體, ''shi hua yiti'') établit que : * La poésie et la peinture partagent le même but : créer un royaume artistique (意境, ''yijing'') où intention et paysage se fondent * Toutes deux doivent transcender la représentation mimétique pour atteindre l'expression spirituelle * La forme doit s'adapter organiquement au contenu, comme l'eau épousant le terrain * Le vide et le plein, le réel et l'illusoire doivent s'équilibrer harmonieusement * Le royaume artistique surgit « au-delà de l'image », dans l'espace de suggestion et d'évocation * L'intégration harmonieuse de la poésie, de la calligraphie et de la peinture crée une synthèse esthétique supérieure Cette conception a profondément structuré l'esthétique chinoise et continue d'influencer la création artistique contemporaine, offrant une alternative remarquable à la séparation occidentale traditionnelle entre les genres artistiques. == Catégories esthétiques spécifiques == === Le souffle vital (氣, ''qi'') === Le concept de ''qi'' (氣, « souffle », « énergie vitale », « flux », « pneuma ») constitue l'un des piliers fondamentaux de la pensée chinoise et occupe une place centrale dans l'esthétique traditionnelle. Irréductible à toute catégorie occidentale unique — ni pure matière ni pur esprit, ni substance ni force —, le ''qi'' désigne le principe dynamique qui anime l'Univers et tous les êtres, la circulation incessante qui relie le Ciel et la Terre, le principe vital qui se manifeste dans toute forme d'existence et d'expression. Dans l'esthétique chinoise, le ''qi'' est ce qui confère à l'œuvre d'art sa vitalité, sa présence et sa puissance d'animation. ==== Les origines cosmologiques du ''qi'' ==== '''Le ''qi'' comme principe primordial''' : Dans la cosmologie chinoise, le ''qi'' est conçu comme le principe primordial (元氣, ''yuanqi'', « souffle originel ») à partir duquel toutes choses se forment. Le ''Livre des Mutations'' (''Yijing'') affirme : « Dans le système du yi, il y a le Grand Terminus (太極, ''Taiji''), qui produit les deux formes élémentaires (陰陽, Yin et Yang). Ces deux formes produisent les quatre symboles emblématiques, qui à leur tour produisent les huit trigrammes ».<ref>''Yijing'', ''Xi Ci'' (Commentaire annexé), cité dans Yuelin Jin (1986). ''Tao, Nature and Man'', Foreign Language Teaching and Research Publishing, p. 33.</ref> Le Grand Terminus (太極, ''Taiji'') désigne le ''qi'' primordial indifférencié avant la division du Ciel et de la Terre. Ce ''qi'' fondamental est la « substance génératrice » (生氣, ''shengqi'') qui donne naissance à toutes choses.<ref>Jin (1986), p. 33-34.</ref> '''Le ''qi'' et la formation de l'Univers''' : Selon la conception traditionnelle, l'Univers se forme par la différenciation du ''qi'' primordial en deux modalités complémentaires : le ''qi'' léger et pur qui s'élève pour former le Ciel, et le ''qi'' lourd et trouble qui descend pour former la Terre.<ref>Liu An, ''Huainanzi'', « Leçons sur le monde humain », cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 222.</ref> Cette différenciation n'est pas définitive : le ''qi'' circule perpétuellement entre le Ciel et la Terre, s'élevant sous forme de vapeurs et d'exhalations subtiles, redescendant sous forme de pluie et de rosée. Cette circulation constitue le rythme fondamental de la vie universelle.<ref>Marcel Granet (1934). ''La pensée chinoise'', Albin Michel, p. 326-327.</ref> ==== Le ''qi'' et les êtres vivants ==== '''La constitution des êtres''' : Tous les êtres sont formés par l'agglutination et la condensation du ''qi''. Comme l'affirme le ''Huainanzi'' : « Les humains sont nés en contenant le ''qi'', et ils meurent quand leur essence est épuisée ».<ref>Yang Quan, ''Wuli Lun'' (Sur la loi des choses), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 226.</ref> Ge Hong (葛洪, 283-343), dans son ''Baopuzi'', déclare : « Du Ciel et de la Terre à toutes choses, rien n'existe sans ''qi'' pour soutenir la vie ».<ref>Ge Hong, ''Baopuzi'', « La sagesse ultime », cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 226.</ref> Le ''qi'' existe chez les humains sous deux formes principales : l'essence vitale (精氣, ''jingqi'', le ''qi'' raffiné) et l'énergie spirituelle (神氣, ''shenqi'', le ''qi'' de l'esprit). Le ''Guanzi'' (管子) analyse ce processus : « Le ''qi'' non obstrué conduit à la vie, et la vie conduit à la pensée, et la pensée conduit à la connaissance ».<ref>''Guanzi'', chapitre « Nei Ye » (Cultivation intérieure), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 226.</ref> '''Le ''qi'', le sang et les viscères''' : Dans la physiologie chinoise, le ''qi'' et le sang (血, ''xue'') constituent les deux principes vitaux complémentaires. Le ''qi'', associé au Yang et au Ciel, représente l'aspect dynamique, chaud et subtil. Le sang, associé au Yin et à la Terre, représente l'aspect substantiel, nourrissant et dense.<ref>Granet (1934), p. 326-328.</ref> Les médecins considèrent que « le ''qi'' est la substance, le ''shen'' (esprit) est la fonction » (氣為體,神為用, ''qi wei ti, shen wei yong'').<ref>Analyse dans Li Zehou (2010). ''The Chinese Aesthetic Tradition'', trad. Maija Bell Samei, University of Hawaii Press, p. 112-115.</ref> ==== Le ''qiyun shengdong'' : la résonnance spirituelle engendre le mouvement ==== '''Le premier principe de Xie He''' : Le concept de ''qiyun shengdong'' (氣韻生動, « la résonnance spirituelle engendre le mouvement ») constitue le premier et le plus important des Six Principes de Xie He pour la peinture. Ce principe affirme que l'œuvre d'art doit manifester le ''qi'' — l'énergie vitale qui anime toutes choses — et créer une résonnance (韻, ''yun'') qui génère le mouvement et la vie.<ref>Susan Bush et Hsio-yen Shih (1985). ''Early Chinese Texts on Painting'', Harvard University Press, p. 11-15.</ref> Le terme ''qiyun'' est composé de ''qi'' (氣, « souffle », « énergie vitale ») et ''yun'' (韻, « résonnance », « harmonie », « charme »). Ensemble, ils désignent la qualité ineffable qui anime une œuvre d'art et la rend vivante. Le caractère ''shengdong'' (生動) signifie littéralement « donner naissance au mouvement » ou « engendrer la vitalité ».<ref>Bush et Shih (1985), p. 12.</ref> '''Zhang Yanyuan et le ''qiyun''''' : Zhang Yanyuan (張彥遠, vers 815-877), dans son ''Lidai minghua ji'' (歷代名畫記, ''Registre des peintures célèbres de toutes les dynasties''), commente : « Sans résonnance spirituelle, l'habileté technique serait futile. La transmission de l'esprit repose sur la bonne conduite morale, et la bonne conduite morale harmonise la résonnance spirituelle. Ainsi, dans l'antiquité, ceux qui excellaient dans la peinture étaient aussi ceux qui pratiquaient la cultivation intérieure ».<ref>Zhang Yanyuan, ''Lidai minghua ji'', cité dans Bush et Shih (1985), p. 53-54.</ref> ==== Le ''qi'' dans la littérature : la théorie du ''wenqi'' ==== '''La vitalité littéraire''' : La théorie de la vitalité littéraire (文氣, ''wenqi'') affirme que les œuvres littéraires, comme tous les êtres vivants, sont animées par un ''qi'' qui leur confère vie et puissance. Ce ''qi'' littéraire est en réalité le ''yuanqi'' (氣元, le ''qi'' fondamental) — la force vitale qui nourrit toutes choses.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 227-228.</ref> Comme le souligne Peng Shi : « Le Ciel et la Terre dotent les gens de leur ''qi'' raffiné, et les individus ont leur propre ''qi'' unique. En le nourrissant, il devient plein et abondant, éclatant parfois à travers l'inspiration — et c'est alors que les œuvres littéraires prospèrent ».<ref>Peng Shi, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 227-228.</ref> '''Le ''qi'' et la vie de l'œuvre''' : Fang Dongshu affirme : « La poésie et la littérature sont l'essence de la vie. Si une œuvre manque de vitalité et ressemble à une découpe de papier ou à une sculpture sans vie, c'est une simple écriture bureaucratique, et l'auteur n'y a aucune part ».<ref>Fang Dongshu, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 228.</ref> Tang Dai déclare : « Le Ciel crée avec vitalité, et la peinture la capture avec le pinceau et l'encre. Le pinceau et l'encre doivent posséder la vitalité de la personnalité, la fusionnant avec la vitalité du Ciel et de la Terre ».<ref>Tang Dai, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 228.</ref> ==== Les catégories esthétiques dérivées du ''qi'' ==== '''La vivacité (生意, ''shengyi'')''' : Han Zhuo, critique d'art de la dynastie Song, affirme : « La peinture devrait capturer l'esprit naturel, exprimant pleinement sa vivacité (生意, ''shengyi''). Ceux qui réussissent dans cet aspect sont accomplis, tandis que ceux qui échouent manquent ».<ref>Han Zhuo, ''Shanshui chunquan ji'' (Collection complète sur la peinture de paysage), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 228.</ref> '''La vigueur (生機, ''shengji'')''' : Cette catégorie désigne la force génératrice qui anime l'œuvre. Les anciens cherchaient précisément cette sorte de vitalité dans la création artistique. Sans elle, l'œuvre est morte, inerte, dépourvue de présence.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 228-229.</ref> '''Le dynamisme (生動, ''shengdong'')''' : Ce terme, qui apparaît dans le premier principe de Xie He, désigne la capacité de l'œuvre à manifester le mouvement de la vie. L'art chinois valorise non la représentation statique, mais la capture du processus vital lui-même.<ref>Bush et Shih (1985), p. 15-17.</ref> ==== Le flux du ''qi'' : le ''qimai'' ==== '''Les canaux du souffle''' : Le concept de ''qimai'' (氣脈, « canaux du ''qi'' » ou « veines du souffle ») désigne les canaux à travers lesquels le ''qi'' circule dans l'œuvre d'art, tout comme il circule dans le corps humain ou dans le paysage naturel. Malgré la nature changeante de l'art littéraire et les divers facteurs en jeu, il devrait toujours y avoir un ''qi'' cohérent qui le traverse.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 229-230.</ref> Comme le note un critique : « Puisque la vitalité des œuvres littéraires ressemble à la circulation de la vitalité dans le Ciel et la Terre, ou au flux sanguin dans le corps humain, si elle ne circule pas, ne deviendra-t-elle pas sans vie ? ».<ref>Cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 228.</ref> Li Yu considère le ''qi'' comme « l'élixir d'or pour un écrivain habile ».<ref>Li Yu, ''Xianqing Ouji'' (Collection de travaux divers de Li Yu), cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 230.</ref> '''Le rythme du ''qi''''' : L'écriture littéraire doit manifester non seulement la présence du ''qi'', mais aussi son rythme. Ce rythme résulte de l'alternance dialectique du Yin et du Yang : ouverture et fermeture, expansion et contraction, relâchement et tension, dispersion et densité, vide et plein, mouvement et immobilité, singularité et complexité.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 229-230.</ref> Lorsque ces éléments opposés se combinent harmonieusement dans une œuvre, celle-ci pulse avec la vitalité de la vie, émanant l'effet esthétique d'un charme artistique vivant (氣韻生動, ''qiyun shengdong'').<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 229-230.</ref> ==== Le ''qi'' et la cultivation personnelle ==== '''L'énergie d'intégrité (正氣, ''zhengqi'')''' : Ce qui confère véritablement le ''qi'' vital à une œuvre, c'est l'énergie d'intégrité (正氣, ''zhengqi'') et l'énergie d'authenticité (真氣, ''zhenqi'') de l'écrivain ou de l'artiste. Sans celles-ci, leurs œuvres émettront une énergie défavorable telle que l'énergie confuse (渾氣, ''hunqi''), l'énergie arrogante (驕氣, ''jiaoqi''), l'énergie obstruée (滯氣, ''zhiqi''), l'énergie médiocre (俓氣, ''jingqi''), et ainsi de suite.<ref>''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 229.</ref> '''La cultivation du ''qi''''' : Les pratiques taoïstes de « cultivation du souffle » (養氣, ''yangqi'') visent à renforcer, purifier et harmoniser le ''qi'' personnel. Ces pratiques incluent la respiration contrôlée, la méditation, les exercices physiques et la régulation de la vie sexuelle.<ref>Granet (1934), p. 418-423.</ref> Mencius affirme : « Je suis doué pour cultiver mon ''qi'' inondant » (我善養吾浩然之氣, ''wo shan yang wu haoran zhi qi''), désignant par là un ''qi'' vaste, puissant et moralement juste qui remplit l'espace entre le Ciel et la Terre.<ref>Mencius, cité dans ''The Spirit of Traditional Chinese Aesthetics'' (2024), p. 90.</ref> ==== Synthèse : le ''qi'' comme principe esthétique fondamental ==== Le concept de ''qi'' (氣, souffle vital) constitue le principe esthétique le plus fondamental de la tradition chinoise. Il établit que : * Toute œuvre d'art véritable doit manifester le ''qi'' — l'énergie vitale qui anime l'Univers * Le ''qiyun shengdong'' (la résonnance spirituelle engendre le mouvement) est le critère suprême de l'excellence artistique * Le ''qi'' de l'œuvre reflète le ''qi'' de l'artiste, qui dépend de sa cultivation morale et spirituelle * Le flux du ''qi'' (氣脈, ''qimai'') doit circuler librement à travers l'œuvre, créant un rythme organique * L'opposition dialectique du Yin et du Yang structure le rythme du ''qi'' * Sans ''qi'', l'œuvre est morte, inerte, dépourvue de présence et de puissance Cette conception holistique, qui refuse toute séparation entre matière et esprit, entre forme et contenu, entre technique et inspiration, continue d'influencer profondément l'esthétique chinoise contemporaine et offre une alternative remarquable aux conceptions occidentales de la création artistique. === Le goût/saveur (味, ''wei'') et la saveur dans le sens (意味, ''yiwei'') === Le concept de ''wei'' (味, « goût », « saveur », « flavor ») occupe une place unique dans l'esthétique chinoise, établissant un pont remarquable entre la sensation gustative et l'appréciation esthétique. Cette conception, qui voit dans la saveur le paradigme de la beauté, distingue radicalement l'esthétique chinoise de la tradition occidentale qui a majoritairement exclu le sens du goût du domaine de l'appréciation esthétique. La théorie du ''wei mei'' (味美, « goût comme beauté ») et sa dérivation, le concept de ''yiwei'' (意味, « saveur dans le sens »), incarnent une approche sensuelle et holistique de la beauté qui valorise l'expérience directe sur l'abstraction conceptuelle. ==== L'explication graphémique : ''wei'' comme synonyme de ''mei'' ==== '''L'étymologie du caractère ''mei'' (美)''' : Dans le ''Shuowen Jiezi'' (說文解字, ''Explication des caractères et analyse des graphies'') de Xu Shen (許慎, 58-148), le caractère ''mei'' (美, beauté) est expliqué comme « douceur » (甘, ''gan''). Il est composé d'un radical « mouton » (羊, ''yang'') et d'un radical « grand » (大, ''da''), car le mouton est la principale source de viande parmi les six types de bétail. Le caractère signifie également « bonté » (善, ''shan'').<ref>Xu Shen (2006). ''Shuowen Jiezi'', Yuelu Academy Press.</ref> Le savant graphémique contemporain Zang Kehe indique que l'explication « le mouton est la principale source de viande » est probablement apparue durant la dynastie Song dans l'édition annotée du ''Shuowen Jiezi'' par Xu Xuan (徐鉉, 916-991).<ref>Zang Kehe (1990). ''Caractères chinois et mentalité esthétique'' (漢字文學與審美心理, ''Hanzi Wenxue He Shenmei Xinli''), Xuelin Press, p. 13.</ref> '''Le lien intrinsèque entre goût et beauté''' : Le plaisir gustatif est considéré comme intimement lié à l'expérience esthétique. Comme l'affirme Duan Yucai (段玉裁, 1735-1835) : « ''Gan'' (douceur) est l'une des cinq saveurs de base, et la beauté de ces cinq saveurs est également appelée ''gan'' (plaisir) ».<ref>Duan Yucai, ''Explication du Shuowen Jiezi'', section 4.1.</ref> Ainsi, le concept de beauté est défini à travers le sens du goût dans la graphémique chinoise ancienne. Le mot le plus proche de la beauté est ''shan'' (善, bon). Comme le note le ''Shuowen Jiezi'' : « Beauté (''mei'') est bonté (''shan'') ».<ref>Xu Shen (2006), ''Shuowen Jiezi''.</ref> ==== Le développement historique de la théorie du ''wei mei'' ==== '''La période des Printemps et Automnes''' : Dans les livres historiques de la période des Printemps et Automnes (770-476 avant notre ère), les sens de la vue, de l'ouïe et du goût sont considérés comme reliés les uns aux autres. Par exemple, dans le ''Commentaire de Zuo'' (左傳, ''Zuozhuan''), les sens fondamentaux de la vue, du toucher et de l'ouïe sont énumérés parallèlement : « Le Ciel a six configurations de base du ''qi'', cinq saveurs de base, cinq accords de base, et tous peuvent apporter un plaisir sensoriel tant qu'ils sont équilibrés et modérés ».<ref>''Commentaire de Zuo'' (左傳, ''Zuozhuan'').</ref> Il est dit que Confucius trouva tant de plaisir dans la musique Shao que « la viande devint sans goût pour lui »,<ref>''Entretiens'' (論語, ''Analectes''), chapitre 7 « Shu Er ».</ref> établissant ainsi la connexion entre le sens de l'ouïe et le sens du goût. '''Laozi et la saveur de la fadeur''' : Laozi trouva la saveur de la fadeur (淡, ''dan'') dans la satisfaction spirituelle apportée par le Dao : « Quand le Dao émerge de son ouverture, il est insipide, n'ayant aucun goût. Regardez-le, vous ne pouvez le voir. Écoutez-le, vous ne pouvez l'entendre. Utilisez-le, vous ne pouvez l'épuiser ».<ref>''Daode Jing'' (道德經, ''Tao Te Ching''), chapitre 35.</ref> Par conséquent, Laozi suggérait que les gens « agissent sans manipuler. S'engagent sans imposer. Goûtent sans goûter » (為無為,事無事,味無味, ''wei wuwei, shi wushi, wei wuwei'').<ref>''Daode Jing'', chapitre 63.</ref> La satisfaction spirituelle est ainsi connectée au sens du goût. '''La période des Royaumes Combattants''' : À cette époque, la beauté fut pour la première fois référée comme saveur. Xunzi (荀子, 313-238 avant notre ère) écrit : « C'est le sentiment humain que le goût et l'odeur qu'on aime sont beaux ».<ref>Xunzi, ''Wangba''.</ref> Le ''Livre des Rites'' (禮記, ''Liji'') affirme : « Le meilleur banquet pour accomplir les rituels devrait avoir de l'eau et du poisson frais. Le porridge de viande devrait être non assaisonné pour prêter une saveur durable » (享祀之禮,水與鮮。肉粥不以味為佳,而以久留其味, ''xiang si zhi li, shui yu xian. Rou zhou bu yi wei wei jia, er yi jiu liu qi wei'').<ref>''Liji'' (禮記, ''Livre des Rites'').</ref> ==== Le ''wei'' dans la critique littéraire ==== '''La dynastie Han''' : Le mot ''meiwei'' (美味, « belle saveur ») fut utilisé pour la première fois dans le ''Lunheng'' (論衡, ''Disquisitions'') de Wang Chong (王充). Wang Chong écrit : « Les mets délicieux pourrissent le ventre, les belles couleurs égarent le cœur » (美味腐腹,好色惑心, ''meiwei fu fu, haose huo xin'').<ref>Wang Chong, ''Lunheng'' (論衡, ''Disquisitions''), chapitre « Yan Du » (言毒), vers 76-84.</ref> Dans le ''Shuowen Jiezi'', Xu Shen utilisa ''mei'' et ''gan'' comme synonymes l'un de l'autre.<ref>Xu Shen (2006), ''Shuowen Jiezi''.</ref> '''L'époque des Six Dynasties''' : Le ''wei'', ou saveur, devint un mot commun en poétique durant l'ère des Six Dynasties (220-589). Liu Xie (劉勰), auteur du premier livre chinois sur la théorie littéraire, le ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit littéraire et la sculpture du dragon''), inventa trois termes : ''ziwei'' (滋味, saveur verbale), ''jingwei'' (境味, saveur formelle) et ''yiwei'' (意味, saveur thématique), pour désigner respectivement la beauté verbale, la beauté formelle et la beauté thématique de la littérature.<ref>Liu Xie, ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit littéraire et la sculpture du dragon''), chapitre « Ming Shi » (明詩, « Élucider la poésie »).</ref> Parmi eux, le ''ziwei'' est considéré comme le critère quintessentiel pour la poésie et la poétique. Comme Zhong Rong (鍾嶸, 468-518) commenta dans le ''Shipin'' (詩品, ''Classement de la poésie'') : « Les poèmes de cinq caractères (五言詩, ''wuyan shi'') ont le plus de saveur (有滋味, ''you ziwei'') parmi tous les genres car c'est un genre bon pour dépeindre les choses et transmettre les sentiments ».<ref>Zhong Rong, ''Shipin'' (詩品, ''Classement de la poésie'').</ref> '''La dynastie Tang''' : Le ''wei'' fut largement utilisé dans la critique littéraire durant la dynastie Tang (618-907), et une œuvre représentative est le ''Ershisi Shipin'' (二十四詩品, ''Vingt-quatre styles de poésie'') de Sikong Tu (司空圖, 837-908). Pour Sikong, « être capable de distinguer les saveurs sert de point de départ pour discuter la poésie » (辨味能為談詩之起點, ''bian wei neng wei tan shi zhi qidian'').<ref>Sikong Tu, ''Ershisi Shipin'' (二十四詩品, ''Vingt-quatre styles de poésie'').</ref> ==== Le ''yiwei'' : la saveur significative ==== '''La profondeur du sens''' : L'appréciation de la beauté intérieure engendre également la théorie de la « saveur significative » (意味, ''yiwei''). Le caractère ''yi'' (意) signifie littéralement « signification » et ''wei'' (味) signifie « saveur », parce qu'une signification profonde laisse une saveur durable.<ref>Yang Zhu (2015). « Poetic Taste and Tasting Poetry », in ''Linking Ancient and Contemporary'', p. 299-316.</ref> Wu Ke exprime cette idée avec éloquence : « Lorsqu'on lit des œuvres bien ornées, on peut être impressionné par leur apparence, mais elles deviennent fades après un certain temps ; ce ne sont que les œuvres qui contiennent une signification profonde qui résistent à des lectures répétées » (文章華藻者,初雖可觀,久則索然;惟意味深長者,百讀不厭, ''wenzhang huacao zhe, chu sui ke guan, jiu ze suoran; wei yiwei shenchang zhe, bai du bu yan'').<ref>Wu Ke, ''Zanghai Shihua'' (藏海詩話, ''Wu Zanghai sur la poésie'').</ref> '''Wang Shizhen et le charme spirituel''' : Wang Shizhen (王士禎, 1634-1711), critique littéraire de la dynastie Qing, citant un ami, affirma : « Il est plus important d'écrire sur l'esprit des choses plutôt que sur leur apparence, et c'est la signification plutôt que l'événement qui importe » (寫神不寫貌,寫意不寫事, ''xie shen bu xie mao, xie yi bu xie shi'').<ref>Wang Shizhen, ''Huacao Mengshi'' (花草夢詩, ''Notes modestes sur les chansons parmi les fleurs et la poésie de la chaumière'').</ref> ==== La saveur de la fadeur (淡味, ''danwei'') ==== '''Laozi et Zhuangzi sur la fadeur''' : Le concept de fadeur fut d'abord proposé par Laozi comme une catégorie esthétique. Comme l'affirme le ''Daode Jing'' : « Le goût du Dao est fade, si calme et reposé (淡然, ''tiandan'') sont ce qu'il valorise ; la victoire par la force des armes est pour lui indésirable ».<ref>''Daode Jing'' (道德經, ''Tao Te Ching'').</ref> Les gens ordinaires tendent à considérer les cinq saveurs comme délicieuses, mais Laozi plaidait contre cela en poursuivant la fadeur. Il croyait que, bien que les cinq saveurs puissent émousser vos papilles gustatives, la saveur du Dao, avec sa fadeur et son absence de goût, surpasse les saveurs limitées et possède une plénitude infinie qui est bien supérieure. Zhuangzi (莊子) fait écho à cette idée en affirmant que « la fadeur est illimitée, et toute beauté en provient » (淡無限,美從出, ''dan wuxian, mei cong chu'').<ref>Zhuangzi (莊子), cité dans Chen (2024). « Zhuangzi's "aesthetic mind" theory from the perspective of art theory », ''Atlantis Press''.</ref> Le goût fade du Dao, qui est sans goût mais inclut toutes les saveurs, est similaire à celui de l'eau. '''La saveur ultime''' : Zhuangzi ajoute : « L'amitié d'un homme de bien est aussi fade que l'eau ; l'amitié d'un homme mesquin est aussi douce que le miel. Pourtant la fadeur de l'homme de bien mène à la proximité, tandis que la sycophantie de l'homme mesquin mène à l'éloignement » (君子之交淡如水,小人之交甘如醴, ''junzi zhi jiao dan ru shui, xiaoren zhi jiao gan ru li'').<ref>Zhuangzi, « Autumn Floods » (秋水, ''Qiu Shui'').</ref> Cette idée de goût fade comme goût suprême influença également le Confucianisme. Comme l'affirme le ''Zhongyong'' (中庸, ''La Doctrine du Milieu'') : « La voie de l'homme de bien est fade mais non lassante » (君子之道,淡而不厭, ''junzi zhi dao, dan er bu yan'').<ref>''Zhongyong'' (中庸, ''La Doctrine du Milieu'').</ref> Le vin mystérieux (玄酒, ''xuanjiu'') et le grand bouillon, qui sont fades et sans goût, sont considérés comme la saveur ultime dans les rituels de culte des ancêtres en raison de leur goût persistant, qui est le fondement des cinq saveurs.<ref>''Liji'' (禮記, ''Livre des Rites'').</ref> ==== L'opposition entre esthétique chinoise et occidentale ==== '''L'exclusion du goût en Occident''' : Dans les théories esthétiques occidentales dominantes, le sens esthétique est distingué de la sensation physique, et la beauté est également différenciée des objets de plaisir sensuel. Par conséquent, le délice gustatif subjectif est facilement exclu de la considération de la beauté.<ref>Gu Ming Dong (2003). « Aesthetic Suggestiveness in Chinese Thought », ''The Journal of Aesthetics and Art Criticism''.</ref> Par exemple, dans le ''Grand Hippias'', Socrate déclara que « le beau est ce qui plaît par l'ouïe et la vue ».<ref>Platon, ''Grand Hippias''.</ref> Cette position fut réitérée par Saint Thomas d'Aquin (1225-1274) : « Les sens les plus intimes sont la vision et l'audition. Nous ne louons que les paysages ou les sons comme beaux, mais n'utilisons jamais le même mot pour les objets d'autre perception sensorielle tels que le goût et l'odorat ».<ref>Saint Thomas d'Aquin, cité dans Collingwood, R. G. (1987). ''Les Principes de l'art'' (藝術原理, ''Yishu Yuanli'').</ref> L'exclusion du goût dans l'esthétique occidentale dominante exerce une influence durable. Comme R. G. Collingwood se plaignit au sujet des esthéticiens modernes dans ''Les Principes de l'art'' : « Nous ne devrions pas, disent-ils, appeler un steak grillé beau. Mais pourquoi pas ? ».<ref>R. G. Collingwood (1987). ''Les Principes de l'art'' (藝術原理, ''Yishu Yuanli''), trad. Wang Zhiyuan et Chen Huazhong, Chinese Social Science Press, p. 40.</ref> '''La spécificité chinoise''' : La caractéristique la plus distinctive de l'esthétique chinoise traditionnelle qui la distingue de son homologue occidentale est que la première voit la saveur comme synonyme de beauté et utilise la saveur pour décrire les sensations perçues par les autres sens.<ref>Sun Chao (2018). « An Interpretation of "Xingwei" », ''Theoretical Studies in Literature and Art'', 38(3), p. 151-159.</ref> ==== Synthèse : le ''wei'' comme paradigme esthétique ==== Le concept de ''wei'' (味, goût/saveur) et sa dérivation ''yiwei'' (意味, saveur significative) établissent que : * La beauté en Chine est fondamentalement liée à l'expérience gustative et sensorielle * Le plaisir esthétique ne se limite pas au visuel et à l'auditif, mais englobe tous les sens * La fadeur (淡, ''dan'') représente paradoxalement la saveur ultime, car elle contient toutes les saveurs * Le ''yiwei'' (saveur significative) désigne la profondeur du sens qui laisse une impression durable * L'esthétique chinoise valorise l'expérience sensuelle directe sur l'abstraction conceptuelle * La saveur persistante (餘味, ''yuwei'', « saveur résiduelle ») est plus précieuse que l'intensité immédiate Cette conception holistique, qui refuse de séparer le plaisir sensuel du plaisir intellectuel, continue d'influencer profondément la culture chinoise et offre une alternative remarquable aux théories esthétiques occidentales qui ont majoritairement exclu le sens du goût du domaine de l'appréciation esthétique. === L'état/royaume (境, ''jing'') et la conception artistique (意境, ''yijing'') === Les concepts de ''jing'' (境, « royaume », « état », « sphère », « frontière ») et de ''yijing'' (意境, « conception artistique », « royaume de signification ») constituent l'un des piliers les plus importants de l'esthétique chinoise traditionnelle. Ces notions, qui articulent la relation entre le monde objectif et la subjectivité créatrice, entre l'extérieur et l'intérieur, entre le visible et l'invisible, sont au cœur de la théorie littéraire et artistique chinoise depuis la dynastie Tang (618-907) et continuent d'exercer une influence profonde sur la création artistique contemporaine. ==== Étymologie et significations premières de ''jing'' (境) ==== '''Les significations originelles''' : Le caractère ''jing'' (境) signifie originellement « périmètre » ou « frontière ».<ref>Key Concepts in Chinese Thought and Culture, « Jing », chinesethought.cn, 2021.</ref> Avec l'introduction du bouddhisme en Chine pendant les dynasties Han tardives, Wei et Jin (II<sup>e</sup>-V<sup>e</sup> siècles), l'idée s'est répandue que le monde physique n'était qu'une illusion et que seul l'esprit était réel dans l'existence. Ainsi, ''jing'' en est venu à être considéré comme un royaume ou une sphère qui pouvait être atteint par les sensibilités de l'esprit.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> '''L'influence bouddhique''' : Le terme fut utilisé pour traduire l'idée d'un royaume mental dans les sutras bouddhiques, un état de cultivation spirituelle atteint après avoir surmonté l'égarement dans le monde matériel.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> Cette transformation sémantique du terme, passant d'une signification spatiale concrète à une dimension spirituelle, a ouvert la voie à son utilisation comme terme technique dans la critique littéraire et artistique. ==== La naissance du concept de ''yijing'' (意境) : Wang Changling ==== '''Wang Changling et les "Trois Royaumes" de la poésie''' : Le terme ''yijing'' (意境) fut proposé pour la première fois par le célèbre poète de la dynastie Tang Wang Changling (王昌齡, vers 689-756 ou 698-756) dans son ouvrage ''Shiyi'' ou ''Shige'' (詩格, ''Principes de poésie'' ou ''Règles de poésie'').<ref>Tang Yanfang (2014). « Yi Jing and Understanding Chinese Poetry », ''Intercultural Communication Studies'', XXIII:1, p. 189.</ref><ref>Key Concepts in Chinese Thought and Culture, « Yijing », chinesethought.cn, 2021.</ref> Dans ce traité, Wang Changling proposa que la poésie possédait « trois royaumes » (三境, ''san jing'') : * Le royaume des choses ou des objets (物境, ''wu jing'') * Le royaume des émotions ou des sentiments (情境, ''qing jing'') * Le royaume de l'idée ou de la signification (意境, ''yi jing'')<ref>Tang Yanfang (2014), p. 189.</ref><ref>Cai Zong-qi (2017). « Wang Changling on Yi and literary creation », ''Lingnan University'', p. 1.</ref> '''L'interaction harmonique entre esprit et réalité''' : Quelle que soit la forme qu'un poème puisse prendre, Wang Changling insistait sur le fait qu'il devait y avoir une interaction harmonique et une référence croisée entre l'esprit subjectif (心, ''xin'') et la réalité objective (境, ''jing''). Dans ses propres mots : « placer l'esprit dans le royaume, regarder le royaume à partir de l'esprit » (處心於境,視境於心, ''chu xin yu jing, shi jing yu xin'').<ref>Tang Yanfang (2014), p. 189.</ref> '''L'influence du bouddhisme Chan''' : Il est significatif que la théorie de ''yijing'' de Wang Changling ait été influencée par la pensée bouddhique Chan, notamment par le concept des « trois mille royaumes en un seul esprit » (一心三千境, ''yi xin san qian jing'') du maître Zhizhe.<ref>« From Master Zhi Zhe's "Three Thousand Realms in One Mind" to Wang Changling's Theory of "Yi Jing" », Semantic Scholar.</ref> Cette influence bouddhique explique la dimension transcendante et méditative du concept de ''yijing''. ==== Le développement de la théorie : Liu Yuxi et la dynastie Tang ==== '''Liu Yuxi et la transcendance de l'objet''' : Le poète Liu Yuxi (劉禹錫, 772-842) de la dynastie Tang fit progresser la théorie en proposant que « la conception esthétique transcende les objets concrets décrits » (境生於象外, ''jing sheng yu xiang wai'').<ref>Guan Yongqiang (2024). « Aesthetic conceptions and cultural symbols in traditional Chinese painting », ''Trans/Form/Ação'', 47:4.</ref> Le texte original déclare : « Un poème peut transmettre le même sens que la prose sans utiliser beaucoup de mots. Ainsi, la poésie est implicite et subtile, un art difficile à maîtriser. La conception poétique transcende souvent ce qui est dénoté par les objets décrits ».<ref>Guan Yongqiang (2024).</ref> Cette proposition marqua une étape importante dans le développement de la théorie de la conception esthétique dans la poésie classique chinoise, établissant que le ''jing'' poétique dépasse toujours la simple représentation des objets physiques pour atteindre une dimension spirituelle et suggestive. ==== Les caractéristiques du ''yijing'' ==== '''La fusion du sens et de la scène''' : Le ''yijing'' se définit comme la combinaison parfaite du message que l'auteur transmet avec les images qu'il utilise dans ses œuvres, donnant libre cours à l'imagination du lecteur.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> Cette fusion est exprimée par la formule classique « fusion des sentiments et du paysage » (情景交融, ''qing jing jiao rong''), où l'émotion et la scène ne peuvent plus être séparées l'une de l'autre.<ref>Tang Yanfang (2014), p. 190.</ref> '''La qualité picturale et l'ambiguïté sémantique intentionnelle''' : Le ''yijing'' présente deux caractéristiques frappantes. D'une part, sa concrétude picturale : la scène comporte des détails iconographiques qui rappellent une peinture. Dans la tradition critique chinoise, la poésie et la peinture sont souvent discutées ensemble, étant considérées comme deux arts apparentés qui partagent des objectifs, des méthodologies et des idées esthétiques.<ref>Tang Yanfang (2014), p. 191.</ref> Les dictons populaires dans les traditions culturelles chinoises « il y a de la peinture dans la poésie » (詩中有畫, ''shi zhong you hua'') et « il y a de la poésie dans la peinture » (畫中有詩, ''hua zhong you shi'') témoignent de la communalité des deux formes d'art dans l'esprit des poètes et artistes chinois.<ref>Tang Yanfang (2014), p. 191.</ref> D'autre part, son flou sémantique intentionnel ou son ambiguïté : la technique de la fusion de l'émotion et de la scène pour créer le ''yijing'' dicte qu'au moment où le poète structure la scène, il procède de manière à laisser suffisamment de « lacunes » et de « trous » dans l'image afin que le lecteur les remplisse en lisant le poème et ainsi réactive, recrée ou, mieux encore, co-crée le monde poétique que le poète a voulu mettre en place.<ref>Tang Yanfang (2014), p. 192.</ref> ==== Wang Guowei et la théorie moderne du ''jingjie'' (境界) ==== '''La synthèse de Wang Guowei''' : Au début du XX<sup>e</sup> siècle, l'érudit Wang Guowei (王國維, 1877-1927) synthétisa et porta à une divulgation cohérente la poétique du ''yijing'' dans ses ''Remarques poétiques dans le monde humain'' (人間詞話, ''Renjian cihua'').<ref>Tang Yanfang (2014), p. 189.</ref> Wang Guowei créa la théorie du ''jingjie'' (境界), dans laquelle il mêla l'esthétique classique occidentale et l'esthétique classique chinoise.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> '''La distinction entre ''yijing'' et ''jingjie''''' : Généralement, le ''yijing'' se réfère à une combinaison parfaite du message que l'auteur transmet avec les images qu'il utilise dans ses œuvres, et il donne libre cours à l'imagination du lecteur. Le concept de ''jingjie'', cependant, met en avant la sublimation des images artistiques par l'intuition mentale et souligne le rôle du monde mental dans l'élévation de l'œuvre d'art à un niveau supérieur.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> '''Les royaumes avec et sans le "je"''' : Dans la préface à la deuxième édition des ''Paroles du monde humain'' (人間詞乙稿序, ''Renjian ci yigao xu''), Wang Guowei regroupa les trois royaumes de la poésie proposés par Wang Changling en un seul royaume appelé ''yijing'', sous lequel il divisa la poésie en trois sous-catégories basées sur l'interaction entre ''yi'' et ''jing'' (« idée et royaume ») ou ''qing'' et ''jing'' (« émotion et scène ») :<ref>Tang Yanfang (2014), p. 189.</ref> « Concernant l'écriture de la poésie, ce qui peut pleinement exprimer les sentiments de l'auteur intérieurement et toucher le lecteur au cœur extérieurement ne sont rien d'autre que deux choses, ''yi'' et ''jing''. La meilleure œuvre de poésie présente la fusion des deux. Viennent ensuite celles qui excellent soit en ''yi'', soit en ''jing'' respectivement. Dans l'un ou l'autre de ces deux scénarios, ''yi'' et ''jing'' doivent être présents ; sinon, cela ne pourrait être appelé poésie. [...] Les deux aspects de ''yi'' et ''jing'' sont souvent entremêlés l'un avec l'autre. L'auteur peut mettre l'accent sur l'un plus que sur l'autre, mais ne peut abandonner l'un pour l'autre. Qu'un poème soit considéré de haute qualité dépend entièrement de s'il a du ''yijing'' ou si son ''yijing'' est profond ou autrement » (文學之事,其內足以攄己而外足以感人者,意與境二者而已。上焉者,意與境渾,其次或以境勝,或以意勝,苟缺其一,不足以言文學。……故二者常互相錯綜,能有所偏重,而不能有所偏廢也。文學之工不工,亦視其意境之有無與其深淺而已, ''wenxue zhi shi, qi nei zu yi shu ji er wai zu yi gan ren zhe, yi yu jing er zhe er yi. Shang yan zhe, yi yu jing hun, qi ci huo yi jing sheng, huo yi yi sheng, gou que qi yi, bu zu yi yan wenxue... gu er zhe chang hu xiang cuo zong, neng you suo pian zhong, er bu neng you suo pian fei ye. Wenxue zhi gong bu gong, yi shi qi yijing zhi you wu yu qi shen qian er yi'').<ref>Tang Yanfang (2014), p. 189-190.</ref> Wang Guowei distingua également deux types de ''jingjie'' : le royaume avec le « je » subjectif (有我之境, ''you wo zhi jing''), où l'on observe les choses à travers le point de vue subjectif du « je » (以我觀物, ''yi wo guan wu''), de sorte que tout est coloré par le sentiment du « je » ; et le royaume sans le sujet « je » (無我之境, ''wu wo zhi jing''), où l'on observe les choses à travers les choses (以物觀物, ''yi wu guan wu''), sans division entre ce qui est le soi et ce qui sont les choses.<ref>Yu Kar Fai Timothy (2023). « Cinematic ideorealm and cinema following Dao », ''Screen'', 64:4, p. 466.</ref> ==== Le ''yijing'' dans la peinture de paysage ==== '''La peinture de montagnes et d'eaux''' : Le ''yijing'' est particulièrement central dans la peinture calligraphique de paysage chinoise, ''shanshui hua'' (山水畫), signifiant littéralement la peinture de « montagnes et eau », qui fut fortement influencée par la philosophie taoïste.<ref>Yu Kar Fai Timothy (2023), p. 464.</ref> Comme genre central de l'art calligraphique d'Asie de l'Est, la peinture de paysage est apparue pour la première fois sur les paravents pliants chinois (屏風, ''pingfeng'') à la fin de la dynastie Han (25-220). Elle fut développée davantage pendant la période chaotique des dynasties Wei, Jin, du Sud et du Nord (265-589) par des intellectuels ermites pour exprimer leur quête de liberté à travers les montagnes et l'eau.<ref>Yu Kar Fai Timothy (2023), p. 464.</ref> '''Zong Bing et la théorie du paysage''' : Le premier théoricien du paysage, Zong Bing (宗炳, 375-443), un ermite taoïste, artiste et critique de la période des dynasties du Nord et du Sud, affirma que le Tao ne se trouve pas à l'extérieur du soi, mais réside dans les montagnes et les eaux. La forme des montagnes et des eaux reflète la présence du Tao, leur conférant une signification sublime.<ref>Guan Yongqiang (2024).</ref> Ainsi, les montagnes et les eaux possèdent « des qualités intrinsèques et un attrait spirituel » (質有趣靈, ''zhi you qu ling''). Zong Bing déclara : « Maintenant, nous déplions le tissu de soie et laissons le paysage de montagne lointaine être capturé. Ce petit morceau de soie peut aussi représenter la forme majestueuse des monts Kunlun et les pics élevés. En peignant verticalement un trait de trois pouces, nous pouvons transmettre la hauteur d'un millier de pieds ; en utilisant l'encre pour dessiner plusieurs pieds horizontalement, nous pouvons dépeindre une distance de cent lieues ».<ref>Guan Yongqiang (2024), citant Huang (2022), p. 93.</ref> '''La méthode des trois distances de Guo Xi''' : Le célèbre peintre lettré et théoricien de la dynastie Song du Nord, Guo Xi (郭熙, 1020-1090), développa la « méthode des trois distances » (三遠法, ''san yuan fa'') à partir de l'idée de « voyager en étant allongé » (臥遊, ''wo you''), qui émergea d'abord dans la période chaotique des dynasties du Nord et du Sud dans l'œuvre de Zong Bing.<ref>Yu Kar Fai Timothy (2023), p. 470.</ref> Les « trois distances » indiquent trois points de vue différents : « la distance de la hauteur » (高遠, ''gao yuan''), du bas vers le haut, regardant vers la montagne ; « la distance de la profondeur » (深遠, ''shen yuan''), du milieu ou du sommet de la montagne regardant vers des vues lointaines ; et « la distance de la largeur » (平遠, ''ping yuan''), du sommet de la montagne regardant vers des vues tout autour.<ref>Yu Kar Fai Timothy (2023), p. 470.</ref> Pour Guo, une peinture contenant les trois distances peut créer le meilleur ''yijing'', en ce que les trois ensemble fournissent une perception que l'on est au milieu du haut et du bas, du proche et du lointain, des montagnes et de l'eau. C'est pourquoi le philosophe français François Jullien voit les peintures de paysage chinoises comme les corrélations « du haut et du bas, de l'immobile et de l'ondulant, de l'opaque et du transparent, du solide et du fluide, et en effet du vu et de l'entendu ».<ref>Yu Kar Fai Timothy (2023), p. 470, citant François Jullien.</ref> À travers une perspective multifocale, « la peinture chinoise s'efforçait de créer une impression intemporelle et communautaire, qui pouvait être perçue par n'importe qui, et pourtant n'était une scène vue par personne en particulier ».<ref>Yu Kar Fai Timothy (2023), p. 470.</ref> ==== Le ''yijing'' comme accomplissement suprême de l'art chinois ==== '''Le critère de qualité artistique''' : Le ''yijing'' est considéré comme l'accomplissement le plus élevé dans la poétique chinoise pour la poésie de nature et, plus généralement, comme le critère de qualité pour toute œuvre littéraire ou artistique.<ref>« On Yijing in Chinese and English Nature Poetry », David Publisher, 2018.</ref> Une œuvre atteignant un haut niveau de ''jingjie'' manifeste la vraie personnalité de l'auteur, transcende l'ordinaire, frappe une corde sensible dans le cœur du lecteur, stimule l'imagination du lecteur et améliore ainsi l'appréciation de son œuvre.<ref>Key Concepts in Chinese Thought and Culture, « Jingjie », chinesethought.cn, 2021.</ref> '''L'héritage et l'influence''' : Après avoir évolué à travers plusieurs dynasties, ce concept s'est développé en un critère important pour juger la qualité d'une œuvre littéraire ou artistique, représentant un accomplissement puisant dans les écrits classiques à travers les âges. Il est également devenu une marque distinctive de toutes les œuvres littéraires et artistiques exceptionnelles.<ref>Key Concepts in Chinese Thought and Culture, « Yijing », chinesethought.cn, 2021.</ref> Le terme représente également une union parfaite entre les pensées et la culture étrangères et celles typiquement chinoises. ==== Synthèse : le ''yijing'' comme sphère esthétique transcendante ==== Le concept de ''yijing'' (意境) établit que : * Le ''yijing'' décrit une expérience esthétique intense dans laquelle la perception d'un objet atteint un royaume d'union parfaite avec l'implication dénotée par l'objet * L'appréciation esthétique dans l'esprit est caractérisée par « projeter le sens dans une scène » et « mêler le sentiment au paysage » (寓意於景,情景交融, ''yu yi yu jing, qing jing jiao rong'') * Contrairement au terme ''yixiang'' (意象, « image »), le ''yijing'' révèle pleinement l'implication et le sens esthétique élevé qu'une œuvre artistique entend délivrer * Le concept s'étend pour inclure d'autres notions telles que sentiment et scène, significations actuelles et implicites, ou esprit et objet * Il élève les œuvres littéraires et artistiques à un nouveau royaume d'appréciation esthétique Cette conception holistique, qui refuse de séparer l'objectif du subjectif, le monde extérieur du monde intérieur, continue d'exercer une influence profonde sur la création et l'appréciation artistiques en Chine et offre une perspective unique sur la nature de l'expérience esthétique. === Le motif/la culture (文, ''wen'') === Le concept de ''wen'' (文, « motif », « culture », « raffinement », « civilisation ») occupe une place centrale dans l'esthétique chinoise et constitue l'un des pivots de la pensée culturelle et philosophique chinoise. Ce terme polysémique, dont les significations se sont enrichies au fil des siècles, incarne la vision chinoise de la beauté comme intrinsèquement liée aux motifs naturels, à l'ornement civilisateur, à l'écriture, à la littérature et à la culture dans son sens le plus large.<ref>Falkenhausen, Lothar von (1996). « The Concept of Wen in the Ancient Chinese Ancestral Cult », ''Chinese Literature: Essays, Articles, Reviews'', 18, p. 1-22.</ref> ==== Étymologie et significations premières de ''wen'' (文) ==== '''L'origine graphique du caractère''' : Le caractère ''wen'' (文) trouve son origine dans la représentation picturale d'un danseur déguisé en oiseau avec des motifs de plumes sur la poitrine. Selon Anne Cheng, « la graphie originelle peut être interprétée comme représentant un danseur déguisé en oiseau avec des motifs plumes sur la poitrine. Par dérivation, on en arrive au sens de 'motif', de 'dessin', ou de l'anglais 'pattern' ».<ref>Cheng, Anne (2002). ''Histoire de la pensée chinoise'', Paris, Éditions du Seuil, p. 93.</ref> '''Les trois significations fondamentales''' : Dès l'antiquité, le terme ''wen'' possède trois significations interconnectées. Premièrement, il désigne les veines naturelles du jade, les motifs cosmiques visibles dans la nature – ce que Karl-Heinz Pohl appelle « pattern/structure » (motif/structure). Deuxièmement, il se réfère aux ornements et décorations, particulièrement ceux visibles sur les bronzes rituels de la dynastie Shang et Zhou. Troisièmement, il renvoie aux signes écrits, aux caractères chinois qui sont eux-mêmes conçus comme des motifs porteurs de sens.<ref>Pohl, Karl-Heinz. « An Intercultural Perspective on Chinese Aesthetics », University of Trier.</ref> ==== ''Wen'' comme motif cosmique et ordre naturel ==== '''Les motifs célestes (天文, ''tianwen'')''' : Dans le ''Yi Jing'' (易經, ''Livre des Mutations''), le concept de ''wen'' apparaît dans le commentaire du digramme Bi (賁, « L'Ornement » ou « La Grâce ») : « En observant les motifs célestes (天文, ''tianwen''), on peut comprendre les changements des quatre saisons. En observant les motifs humains (人文, ''renwen''), on peut transformer et accomplir le monde ».<ref>''Yi Jing'', commentaire du trigramme Bi (賁).</ref> Les motifs célestes (''tianwen'') désignent les régularités observables dans le mouvement des astres, la succession du jour et de la nuit, l'alternance des saisons. Ces patterns naturels manifestent l'ordre cosmique (天道, ''tiandao''), la loi universelle qui gouverne les mouvements des corps célestes. Comme l'explique le philosophe chinois Guo Qiyong, « ''Tianwen'' se réfère à la loi universelle qui gouverne les mouvements des corps célestes, la rotation des quatre saisons, la succession du jour et de la nuit, et les changements météorologiques ».<ref>Guo Qiyong (2022). ''The Spirit of Chinese Confucianism'', Singapore, Springer, p. 361.</ref> '''La connexion entre nature et culture''' : L'idée fondamentale de la pensée esthétique chinoise est que les ''wen'' – les motifs, ornements et productions culturelles – ne sont pas des créations arbitraires de l'homme, mais plutôt des manifestations ou des prolongements des motifs naturels observables dans le cosmos. Dans cette perspective, la culture humaine (''renwen'') doit s'harmoniser avec les patterns naturels (''tianwen''). Comme le dit Anne Cheng, « ''Wen'', de dessin aux fonctions magiques dans une mentalité religieuse de type animiste, en vient à désigner de manière générale un signe, en particulier un signe écrit, fondement même de la culture ».<ref>Cheng (2002), p. 93.</ref> ==== ''Wen'' et ''zhi'' (質) : ornement et substance ==== '''La paire conceptuelle ''wen''-''zhi''''' : L'un des débats esthétiques les plus importants de la tradition chinoise concerne la relation entre ''wen'' (文, ornement, forme extérieure, raffinement culturel) et ''zhi'' (質, substance, essence intérieure, nature brute). Cette opposition dialectique structure une grande partie de la réflexion esthétique et morale chinoise.<ref>Shen, Jiahui (2023). ''Wen and Zhi as a Conceptual Pair in Early Chinese Thought'', Master Thesis, Cornell University.</ref> '''La position confucéenne de l'équilibre''' : Dans les ''Entretiens'' (論語, ''Lunyu''), Confucius établit la nécessité d'un équilibre entre ''wen'' et ''zhi'' : « Lorsque la substance (質, ''zhi'') l'emporte sur le raffinement (文, ''wen''), on obtient la rusticité. Lorsque le raffinement l'emporte sur la substance, on obtient le pédantisme. C'est seulement lorsque le raffinement et la substance sont en équilibre harmonieux (文質彬彬, ''wen zhi bin bin'') que l'on obtient l'homme de bien (君子, ''junzi'') ».<ref>''Entretiens'' (論語, ''Lunyu''), VI, 18.</ref> Cette formulation célèbre établit que ni l'ornement pur (qui serait superficiel) ni la substance brute (qui serait grossière) ne sont suffisants. C'est leur harmonie qui produit la véritable excellence esthétique et morale. Comme l'explique l'article « The Embodiment of the Idea of the 'Golden Mean' in the Aesthetics of Confucius », Confucius « préconisait l'égalité entre ''wen'' (apparence) et ''zhi'' (essence), qui devraient se compléter mutuellement et correspondre au principe du juste milieu ».<ref>« The Embodiment of the Idea of the 'Golden Mean' in the Aesthetics of Confucius » (2024), ''History of Philosophy & Logic'', 45:4.</ref> ==== ''Wen'' comme culture et civilisation ==== '''Le passage du motif à la culture''' : Au cours de la dynastie des Zhou occidentaux, le terme ''wen'' subit une transformation sémantique majeure, passant du sens de « motif décoratif » à celui de « culture », « civilisation » et « raffinement culturel ». Le roi Wen (文王, ''Wen Wang''), fondateur de la dynastie Zhou, reçut ce nom posthume précisément en raison de son excellence culturelle et civilisatrice.<ref>Cheng (2002), p. 93.</ref> '''Les motifs humains (人文, ''renwen'')''' : Le terme ''renwen'' (人文, littéralement « motifs humains ») en vint à désigner l'ensemble de la culture humaine, comprenant les rites (禮, ''li''), la musique (樂, ''yue''), l'éducation, les codes et les institutions. Selon l'article « Philosophical implications of the civilization imagery in ancient China », « Dans la Chine ancienne, ''renwen'' se réfère à l'éducation conforme aux Rites (禮, ''li'') et à la Musique (樂, ''yue''), ou aux rituels musicaux établis par le duc de Zhou ».<ref>« Philosophical implications of the civilization imagery in ancient China » (2024), ''Guangming Daily'', June 25.</ref> '''La culture de rite et musique''' : La « culture de rite et musique » (禮樂文化, ''li yue wenhua'') de la dynastie Zhou, que Confucius admirait profondément, incarnait cette vision du ''wen'' comme civilisation raffinée. Confucius déclarait : « Je suis un transmetteur et non un créateur. J'ai foi dans les anciens et les aime. Je me permettrai de me comparer au vieux Peng. Les Zhou ont suivi les systèmes rituels des Xia et des Shang. Comme sa culture (文, ''wen'') est riche et splendide ! Je suis un partisan des Zhou ».<ref>''Entretiens'' (論語, ''Lunyu''), III, 14 ; VII, 1.</ref> ==== ''Wen'' comme écriture et littérature ==== '''L'écriture comme manifestation du ''wen''''' : Dans la pensée chinoise, l'écriture elle-même est conçue comme une forme de ''wen'' – les caractères chinois sont des « motifs culturels » qui capturent et transmettent le sens. Les signes écrits « participent du passage d'une pratique divinatoire à une pensée cosmologique. Les signes écrits, dans leur lien originel avec la divination, sont investis d'un pouvoir magique, incantatoire, qui leur restera associé travers toutes les formes ultérieures de l'expression écrite, poésie et calligraphie tout particulièrement ».<ref>Cheng (2002), p. 148.</ref> '''La littérature et l'art d'écrire''' : Le terme ''wen'' en vint à désigner la littérature et l'art d'écrire dans leur sens le plus élevé. Liu Xie (劉勰, vers 465-522), dans son ''Wenxin diaolong'' (文心雕龍, ''L'Esprit littéraire et la sculpture du dragon''), le premier grand traité de théorie littéraire chinoise, définit ainsi le ''wen'' : « Les ouvrages qui traitent des principes universels de la grande triade Ciel-Terre-Homme s'appellent ''jing'' (經, classiques). Ils représentent le Dao suprême dans sa permanence, grande leçon immuable. Voilà pourquoi ils sont à l'image du Ciel et de la Terre, se modèlent sur les esprits et les divinités, participent de l'ordre des choses et règlent les affaires humaines ».<ref>Liu Xie, ''Wenxin diaolong'' (文心雕龍), cité dans Cheng (2002), p. 148.</ref> '''Les motifs décoratifs traditionnels (紋樣, ''wenyang'')''' : Dans les arts décoratifs chinois, le terme ''wenyang'' (紋樣) désigne les motifs traditionnels qui ornent la céramique, les textiles, les bronzes et autres objets d'art. Ces motifs, loin d'être purement décoratifs, sont porteurs de significations symboliques et cosmologiques. Par exemple, les « motifs de nuages et de tonnerre » (雲雷紋, ''yunleiwen'') qui apparaissent fréquemment sur les bronzes rituels de la dynastie Shang représentent les forces cosmiques de la nature.<ref>« Chinese Cloud and Thunder Patterns: Yun Lei Wen » (2024), ''Chinese Showcase'', May 27.</ref> ==== L'esthétique du ''wen'' dans la tradition chinoise ==== '''L'opposition entre esthétiques chinoise et occidentale''' : Selon Yang Zhu, l'étude intitulée « The Aesthetic Standard of Wen: A Comparative Study of Chinese and Western Early Artworks » souligne que « les motifs décoratifs denses et riches sur les bronzes en Chine représentent une forte appréciation esthétique des motifs/ornements, tandis que leurs homologues en Occident démontrent une orientation esthétique enracinée dans la science ».<ref>Yang Zhu (2011). « The Aesthetic Standard of Wen: A Comparative Study of Chinese and Western Early Artworks », ''Asian Studies'', II:2, p. 37-67.</ref> Cette différence fondamentale révèle que l'esthétique chinoise valorise l'ornement et le motif comme manifestations visibles de l'ordre cosmique et moral, tandis que l'esthétique occidentale classique, particulièrement grecque, privilégie la représentation naturaliste du corps humain nu. '''Les motifs dans la nature (自然之文, ''ziran zhi wen'')''' : Le critique littéraire de la dynastie Qing, Ye Xie (葉燮, 1627-1703), exprime l'idée de « règles vivantes » (活法, ''huofa'') en utilisant l'image des nuages sur le Mont Tai. Selon la traduction de Karl-Heinz Pohl, « Dans le Ciel et la Terre, les plus grandes formes de ''wen'' (motif/littérature) sont le vent et les nuages, les pluies et le tonnerre. Leurs mutations et transformations ne peuvent être sondées et n'ont ni limite ni frontière : elles sont la manifestation la plus élevée de l'esprit (神, ''shen'') dans l'univers et la perfection du ''wen'' ».<ref>Ye Xie, cité dans Pohl, Karl-Heinz, « An Intercultural Perspective on Chinese Aesthetics », p. 4.</ref> Cette citation illustre parfaitement comment les phénomènes naturels sont conçus comme les manifestations suprêmes du ''wen'' cosmique, que les artistes et écrivains humains cherchent à imiter et à capturer dans leurs propres créations. ==== ''Wen'' et la voie royale (王道, ''wangdao'') ==== '''La civilisation par le ''wen''''' : Dans la philosophie politique confucéenne, le ''wen'' est associé à la « voie royale » (王道, ''wangdao''), par opposition à la « voie hégémonique » (霸道, ''badao'') fondée sur la force militaire. La voie royale gouverne par la culture, l'éducation et l'exemple moral plutôt que par la coercition. Comme l'explique l'article « Philosophical implications of the civilization imagery in ancient China », « La phrase chinoise ''wenming yizhi'' (文明以止) signifie que la Voie de la civilisation dans le monde consiste pour les dirigeants à agir selon le principe révélé par la loi cosmologique, en choisissant un moyen non-violent dans la gouvernance du monde ».<ref>« Philosophical implications of the civilization imagery in ancient China » (2024).</ref> '''Le caractère national chinois''' : Selon Qian Mu (錢穆), éminent historien chinois du XX<sup>e</sup> siècle, « En fait, la nation chinoise a toujours été dans un processus d'absorption, d'intégration, d'expansion et de renouvellement continus. Cependant, son courant principal, toujours présent et très évident, n'est ni englouti ni emporté par les nouveaux courants ».<ref>Qian Mu (1988). ''An Introduction to the History of Chinese Culture'', Shanghai Sanlian Bookstore, p. 19, cité dans Guo (2022), p. 361.</ref> Cette capacité d'assimilation culturelle est précisément une manifestation du pouvoir civilisateur du ''wen''. ==== Débats et tensions autour du ''wen'' ==== '''La critique taoïste et la « destruction de la substance »''' : Les penseurs taoïstes, notamment Zhuangzi, critiquèrent l'excès de ''wen'' comme artificiel et contraire à la nature spontanée (自然, ''ziran''). Dans le chapitre « Mending Nature » (繕性, ''Shan Xing'') du ''Zhuangzi'', il est affirmé que « les formes ont détruit la substance (primilale) » (文滅質, ''wen mie zhi'').<ref>Shen, Jiahui (2023), p. 4.</ref> Le ''Huainanzi'' (淮南子) élabore cette critique, soulignant comment la poursuite du ''wen'' a perturbé l'équilibre naturel, entraînant une transgression et une destruction inhérentes de ''zhi'' (質), qui représente la simplicité et la nature intrinsèque. Ces textes démontrent qu'au cours de la dynastie Han, la paire conceptuelle ''wen''-''zhi'' revêtait une importance significative, avec des penseurs exprimant leurs perspectives dans le débat sur l'ordre civil et l'harmonie sociale. '''Les trois dynasties et l'alternance de la simplicité et du raffinement''' : Dans le ''Chunqiu fanlu'' (春秋繁露, ''Luxuriantes rosées des Annales des Printemps et Automnes''), Dong Zhongshu (董仲舒) propose la théorie des « Trois dynasties alternant les régulations de simplicité et de raffinement » (三代改制質文, ''san dai gai zhi zhi wen''). Selon cette théorie, les dynasties doivent alterner entre emphase sur la simplicité (質, ''zhi'') et emphase sur le raffinement (文, ''wen'') selon le mandat du Ciel.<ref>Shen, Jiahui (2023), p. 5.</ref> ==== Synthèse : le ''wen'' comme vision esthétique globale ==== Le concept de ''wen'' (文) établit que : * La beauté et la culture ne sont pas arbitraires mais reflètent les motifs naturels du cosmos (天文, ''tianwen'') * L'ornement et la substance doivent être en équilibre harmonieux (文質彬彬, ''wen zhi bin bin'') * La civilisation humaine (人文, ''renwen'') doit s'harmoniser avec l'ordre naturel * L'écriture, la littérature et les arts sont des manifestations du ''wen'' cosmique * Le gouvernement civilisé s'appuie sur la culture et l'éducation plutôt que sur la force * Les motifs décoratifs ne sont pas purement esthétiques mais porteurs de significations cosmologiques et morales Cette conception holistique du ''wen'' révèle une vision du monde dans laquelle nature, culture, moralité, politique et esthétique forment un continuum harmonieux. Elle distingue fondamentalement l'approche chinoise de la beauté de l'approche occidentale classique et continue d'influencer profondément la pensée esthétique chinoise contemporaine. == Influences et dialogues interculturels == === Comparaison avec l'esthétique occidentale === La comparaison entre l'esthétique chinoise et l'esthétique occidentale révèle des différences fondamentales qui ne sont pas simplement d'ordre stylistique, mais touchent aux fondements philosophiques, ontologiques et épistémologiques des deux traditions. Ces différences, loin d'être de simples curiosités historiques, reflètent des choix primordiaux concernant la nature de l'art, la fonction de la beauté, le rôle de l'artiste et la place de l'esthétique dans la société. ==== Les fondements ontologiques et épistémologiques ==== '''Être versus devenir''' : La tradition esthétique occidentale, héritière de la philosophie grecque, s'est largement construite sur une ontologie de l'être, privilégiant la permanence, la substance et les formes fixes. Comme l'observe Karl-Heinz Pohl, « la pensée occidentale commence par poser un moi-sujet qui, en pensant, se constitue comme objet premier et suffisant ».<ref>Pohl, Karl-Heinz (2017). « Chinese Aesthetics and Kant », University of Trier, p. 1.</ref> Cette primauté du sujet pensant conduit à une séparation entre le sujet observateur et l'objet observé, distinction fondamentale qui structure l'approche occidentale de l'art. En contraste, la pensée esthétique chinoise se fonde sur une ontologie du devenir et du processus, privilégiant le flux, la transformation et l'interdépendance. François Jullien souligne que « tandis que l'esthétique européenne s'est focalisée sur la présence et cherche à révéler la forme aussi clairement que possible, la peinture chinoise concerne ce qui est absent : elle dissout les formes tracées et leurs frontières, les rend évasives, commence à les oblitérer et les ouvre sur leur absence ».<ref>Jullien, François (2022). ''The Great Image Has No Form'', University of Chicago Press, cité dans Garage MCA, 2022.</ref> '''Mimesis versus suggestivité''' : La tradition occidentale, depuis Platon et Aristote, a accordé une place centrale au concept de mimesis (μίμησις), l'imitation de la nature. Aristote définissait l'art comme imitation de la nature dans sa créativité, établissant ainsi un rapport de représentation entre l'œuvre et le monde.<ref>Aristote, ''Poétique'', cité dans Pohl (2017), p. 3.</ref> Cette conception mimétique implique que l'artiste cherche à capturer et reproduire fidèlement les apparences du monde visible. L'esthétique chinoise, en revanche, privilégie la suggestivité (暗示, ''anshi'') et l'évocation sur la représentation directe. Comme l'exprime Sikong Tu (司空圖, 837-908), la poésie doit transmettre « des images au-delà des images » (象外之象, ''xiang wai zhi xiang'').<ref>Sikong Tu, cité dans Pohl, Karl-Heinz (2012). « Chinese and Western Aesthetics », University of Trier, p. 7.</ref> Cette approche ne cherche pas à reproduire les apparences mais à évoquer l'essence spirituelle et le souffle vital qui animent les phénomènes. Eva Kit Wah Man établit une distinction importante entre la notion chinoise de ''moxie'' (摹寫, imitation/copying) et la mimesis platonicienne : « Alors que la mimesis platonicienne implique une dévalorisation de l'art comme copie d'une copie, le ''moxie'' chinois est un processus d'apprentissage et de transmission qui vise à capter l'esprit (神, ''shen'') des œuvres des maîtres ».<ref>Man, Eva Kit Wah (2013). « Influence of Global Aesthetics on Chinese Aesthetics: The Adaptation of Moxie », ''Contemporary Aesthetics'', 11.</ref> ==== Les sens privilégiés et la hiérarchie sensorielle ==== '''La vision et l'audition versus tous les sens''' : Dans la tradition occidentale, depuis Platon, une hiérarchie des sens s'est établie privilégiant la vue et l'ouïe comme les seuls sens véritablement esthétiques. Comme le rappelle le philosophe, « Socrate déclara dans le ''Grand Hippias'' que 'le beau est ce qui plaît par l'ouïe et la vue' ».<ref>Platon, ''Grand Hippias'', cité dans Gu Ming Dong (2003). « Aesthetic Suggestiveness in Chinese Thought », ''The Journal of Aesthetics and Art Criticism''.</ref> Saint Thomas d'Aquin réitéra cette position : « Les sens les plus intimes sont la vision et l'audition. Nous ne louons que les paysages ou les sons comme beaux, mais n'utilisons jamais le même mot pour les objets d'autre perception sensorielle tels que le goût et l'odorat ».<ref>Saint Thomas d'Aquin, cité dans Pohl (2017), p. 10.</ref> La tradition chinoise, en revanche, n'établit pas une telle hiérarchie sensorielle rigide. Le goût (味, ''wei''), l'odorat, le toucher sont tous considérés comme des voies légitimes vers l'expérience esthétique. Comme nous l'avons vu précédemment, la saveur est même considérée comme un paradigme de la beauté dans la pensée chinoise, une conception qui serait impensable dans l'esthétique occidentale classique. ==== Le rôle de l'artiste et la création artistique ==== '''Originalité versus perfection''' : Karl-Heinz Pohl observe une différence fondamentale dans ce qui est valorisé chez l'artiste : « Concernant l'art beau du génie, Kant souligne l'aspect de l'originalité. Cela ne trouve pas beaucoup de correspondance dans la pensée chinoise. Pour l'art occidental, particulièrement pour la période romantique et moderne, cette emphase a eu des conséquences profondes, devenant la caractéristique dominante d'une œuvre d'art. En contraste, l'esthétique chinoise met plus l'accent sur la perfection (工, ''gong''), à la fois à travers l'orientation sur les modèles passés et la créativité naturelle ».<ref>Pohl (2012), p. 9.</ref> Cette différence n'est pas anodine. Elle implique que l'artiste occidental romantique et moderne cherche constamment à se démarquer, à innover, à rompre avec la tradition, tandis que l'artiste chinois traditionnel cherche à s'inscrire dans une lignée, à perfectionner sa technique à travers l'étude des maîtres, tout en exprimant sa propre personnalité de manière subtile. '''Initiative du sujet versus disponibilité''' : François Jullien développe une distinction cruciale entre l'« initiative du sujet » propre à la tradition occidentale et la « disponibilité » (可得性, ''ke de xing'') valorisée en Chine. Dans la perspective occidentale post-cartésienne, l'artiste est un sujet autonome qui projette son intention sur la matière, qui impose sa volonté créatrice au monde. Le processus créatif est conçu comme une lutte, un effort de la volonté pour faire advenir une forme conçue intellectuellement.<ref>Jullien, François (2015). ''De l'Être au Vivre : Lexique euro-chinois de la pensée'', Gallimard, p. 45-67.</ref> Dans la tradition chinoise, l'artiste cultive plutôt une disposition intérieure de disponibilité qui lui permet de se mettre en phase avec le flux du monde, de capter le souffle vital (氣, ''qi'') et de le laisser s'exprimer à travers lui. Comme l'exprime le peintre Shi Tao (石濤, 1642-1707), « la peinture n'est pas un travail mais une transformation ».<ref>Shi Tao, cité dans Yu Kar Fai Timothy (2023). « Cinematic ideorealm and cinema following Dao », ''Screen'', 64:4, p. 465.</ref> ==== Le traitement de l'espace et du vide ==== '''Plein versus vide''' : Une des différences les plus frappantes entre les traditions picturales chinoise et occidentale concerne le traitement de l'espace. La peinture occidentale, particulièrement depuis la Renaissance, a développé la perspective linéaire qui cherche à créer une illusion de profondeur sur une surface plane, remplissant l'espace pictural d'objets représentés avec précision.<ref>« Between emptiness and reality: from the white space in Chinese painting to the philosophy of form in western art » (2025), ''Trans/Form/Ação''.</ref> La peinture chinoise, en revanche, valorise le vide (虛, ''xu'') autant que le plein (實, ''shi''). Les espaces vides ne sont pas de simples fonds neutres mais des éléments actifs de la composition. Comme l'explique un article récent, « l'art chinois souligne l'importance du vide et de la conception artistique (意境, ''yijing''), reflétant l'accent mis sur la totalité et la signification intrinsèque. L'art occidental, en revanche, exprime sa préoccupation pour la relation entre les individus et le monde extérieur à travers la poursuite de la rationalité et du réalisme ».<ref>« Between emptiness and reality » (2025).</ref> ==== La relation entre l'homme et la nature ==== '''Maîtrise versus harmonie''' : Dans la tradition occidentale, particulièrement depuis la Renaissance et l'avènement de la science moderne, la nature est souvent conçue comme un objet à connaître, à maîtriser, à dominer. L'artiste, armé de sa technique et de sa connaissance de l'anatomie et de la perspective, cherche à capturer la nature, à la soumettre à sa volonté créatrice. La philosophie esthétique chinoise, profondément influencée par le taoïsme et le confucianisme, prône plutôt l'harmonie entre l'homme et la nature, l'idéal de « l'unité du Ciel et de l'Homme » (天人合一, ''tian ren he yi''). Comme le note un article comparatif, « en termes de relation entre l'homme et la nature, tandis que la philosophie chinoise préconise 'l'harmonie entre l'homme et la nature' et 'l'unité du sujet et de l'objet', la philosophie occidentale soutient la relation opposée entre l'homme et la nature ».<ref>« Aesthetic Comparison of Chinese and Western Landscape Culture » (2018), ''Advances in Social Science, Education and Humanities Research''.</ref> ==== Le rôle de la morale et de l'éthique ==== '''L'autonomie de l'art versus l'intégration morale''' : Une des révolutions majeures de l'esthétique occidentale moderne, particulièrement depuis Kant, a été l'affirmation de l'autonomie de l'art et du jugement esthétique. Kant distingue soigneusement le beau de l'agréable et du bon, établissant que le jugement esthétique est désintéressé et ne doit pas être confondu avec des considérations morales ou utilitaires.<ref>Kant, Immanuel, ''Critique de la faculté de juger'', cité dans Pohl (2017), p. 5.</ref> Dans la tradition chinoise, en revanche, il n'existe pas de séparation nette entre l'esthétique et l'éthique. La beauté (美, ''mei'') est intrinsèquement liée à la bonté (善, ''shan''). Comme nous l'avons vu précédemment, le ''Shuowen Jiezi'' définit ''mei'' comme ''shan''. L'art, loin d'être autonome, est conçu comme un moyen de cultivation morale et spirituelle. Confucius affirmait : « Se triompher soi-même et revenir aux rites, voilà ce qu'est l'humanité » (克己復禮為仁, ''ke ji fu li wei ren''), établissant un lien indissoluble entre cultivation esthétique (les rites incluent la musique et les arts) et perfection morale.<ref>''Analectes'', XII, 1.</ref> ==== Le mode de pensée : analytique versus corrélationnel ==== '''Logique analytique versus pensée corrélative''' : Karl-Heinz Pohl souligne une différence fondamentale dans le mode de pensée : « Le mode occidental, avec l'écriture de Kant ou Hegel comme typique de l'approche occidentale en général, est hautement analytique, en même temps très systématique, créant un système complexe de pensée. C'est sans doute sa force, mais, considérant son caractère parfois tortueux et abstrait, c'est aussi sa faiblesse ».<ref>Pohl (2012), p. 10.</ref> La pensée chinoise, en revanche, procède davantage par corrélation et association que par analyse et décomposition. Au lieu de diviser les phénomènes en éléments constitutifs pour les étudier séparément, elle cherche à comprendre les relations et les correspondances entre les choses. Cette approche corrélative se manifeste dans la théorie du yin et du yang, dans les cinq éléments (五行, ''wuxing''), et dans la structure même de la langue chinoise qui privilégie la parataxe sur l'hypotaxe.<ref>Jullien (2015), p. 123-145.</ref> Comme l'explique Benoît Vermander, « contrairement au récit dominant selon lequel la pensée occidentale s'organise autour d'une ontologie qui présuppose l'existence d'une catégorie maîtresse, l'Être, la pensée chinoise ancienne serait née de spéculations divinatoires qui ont conduit à mettre l'accent sur la fluidité de tous les phénomènes et formes de vie, à se concentrer sur les relations gouvernant le passage d'un état de la matière et d'un état des affaires à un autre ».<ref>Vermander, Benoît (2022). ''The Encounter of Chinese and Western Philosophies'', Brill, p. 8-9.</ref> ==== La temporalité et la narration ==== '''Temps linéaire versus temps cyclique''' : La peinture occidentale traditionnelle, particulièrement dans la peinture d'histoire et la peinture narrative, cherche souvent à capturer un moment décisif dans une séquence temporelle linéaire. Lessing, dans son ''Laocoon'', établit une distinction nette entre les arts de l'espace (peinture, sculpture) et les arts du temps (poésie, musique), distinction qui structure profondément la réflexion esthétique occidentale.<ref>« On the Relationship Between Poetry and Painting from the Perspective of Chinese and Western Culture » (2022), ''BCP Social Sciences & Humanities''.</ref> La conception chinoise du temps dans l'art est plus cyclique et non-linéaire. Les rouleaux horizontaux (手卷, ''shoujuan'') se déploient progressivement, invitant le spectateur à un voyage temporel qui n'a ni début ni fin absolus. La peinture chinoise intègre souvent poésie et calligraphie, fusionnant ainsi les arts de l'espace et du temps d'une manière qui défie la distinction de Lessing. ==== Synthèse : deux visions du monde ==== Les différences entre l'esthétique chinoise et l'esthétique occidentale ne sont pas de simples variations stylistiques mais reflètent des choix philosophiques fondamentaux concernant : * La nature de la réalité : être versus devenir * Le mode de connaissance : analyse versus corrélation * Le rôle du sujet : initiative versus disponibilité * La fonction de l'art : représentation versus évocation * Le rapport à la nature : maîtrise versus harmonie * La relation entre esthétique et éthique : autonomie versus intégration Comme le résume Karl-Heinz Pohl dans son interview, « l'esthétique était initialement aussi une importation occidentale pour la Chine. Cependant, si l'on comprend l'esthétique comme philosophie de l'art, alors les intellectuels chinois ont compris très tôt que cette discipline correspondait très bien à leur propre tradition culturelle. Lorsqu'ils ont commencé à s'engager avec la culture occidentale au tournant de 1900, les intellectuels chinois ont constaté que l'Occident était façonné par la religion (le christianisme), alors que la Chine était façonnée par l'esthétique. L'esthétique a ainsi été comprise comme l'équivalent fonctionnel de la religion ».<ref>Pohl, Karl-Heinz (2022). « Karl-Heinz Pohl on Confucian philosophy and Chinese aesthetics », interview, ''Chinese Social Sciences Today'', July 12.</ref> Ces différences, loin d'établir une hiérarchie entre les deux traditions, révèlent plutôt la richesse et la diversité des réponses humaines aux questions fondamentales de l'art et de la beauté. Elles invitent à un dialogue fécond et à une reconnaissance mutuelle des ressources que chaque tradition peut offrir à la réflexion esthétique contemporaine. === Li Zehou et l'esthétique chinoise moderne === Li Zehou (李澤厚, 1930-2021) est considéré comme l'un des philosophes chinois les plus influents de l'ère contemporaine et le penseur majeur qui a su ressaisir et reformuler l'esthétique chinoise traditionnelle pour l'époque moderne.<ref>Rošker, Jana S. (2020). ''Becoming Human: Li Zehou's Ethics'', Brill, p. ix.</ref> Son œuvre, particulièrement développée durant la période dite du « Nouvel Éclairage » chinois des années 1980, a marqué un tournant décisif dans la compréhension moderne de l'esthétique chinoise en proposant une synthèse originale entre tradition confucéenne, matérialisme marxiste et philosophie kantienne.<ref>Sernelj, Teja (2020). « Different Approaches to Modern Art and Society: Li Zehou versus Xu Fuguan », ''Asian Studies'', 8:1, p. 77-98.</ref> ==== Le contexte intellectuel : le « Nouvel Éclairage » des années 1980 ==== '''La renaissance intellectuelle post-maoïste''' : La décennie entre la publication de sa ''Critique de la philosophie critique'' (批判哲學的批判, ''Pipan zhexue de pipan'') sur Kant en 1979 et celle de ''La tradition esthétique chinoise'' (華夏美學, ''Huaxia meixue'') en 1989 marqua le « mouvement de libre pensée » en Chine moderne, témoignant des traductions d'œuvres philosophiques occidentales telles que ''Être et Temps'' de Heidegger et ''L'Être et le Néant'' de Sartre.<ref>Zou, Hui (2016). « Li Zehou. The Chinese Aesthetic Tradition », ''Montreal Architectural Review'', 3, p. 87.</ref> Durant cette période, l'influence de l'existentialisme occidental était prévalente sur les campus chinois, où universitaires et artistes cherchaient passionnément une nouvelle compréhension de l'humanité après la Révolution culturelle. C'est dans ce contexte que Li Zehou poursuivit son « voyage solitaire » en faveur de l'esthétique traditionnelle chinoise.<ref>Zou (2016), p. 87.</ref> '''Le rôle de Li Zehou comme intellectuel phare''' : Li Zehou appartient aux intellectuels les plus connus de l'« Éclairage chinois » des années 1980, un mouvement intellectuel lié à l'émergence d'une économie de marché ouverte en Chine.<ref>« Growing up (and old) with Chinese philosopher Li Zehou » (2021), ''Think China'', November 18.</ref> Comme le note un critique, « sa philosophie intrigue constamment son public pour qu'il réfléchisse à ce qui manque fondamentalement dans la Chine contemporaine et à ce qui est le plus précieux dans la culture chinoise ».<ref>Zou (2016), p. 87-88.</ref> ==== Les concepts centraux de la philosophie esthétique de Li Zehou ==== '''L'ontologie anthropo-historique (人類學歷史本體論, ''renleixue lishi bentilun'')''' : Li Zehou a développé ce qu'il appelle une « ontologie anthropo-historique », qui diffère fondamentalement de la métaphysique occidentale traditionnelle. Dans son cadre conceptuel, l'ontologie ne se réfère pas à une réalité transcendante séparée du monde phénoménal, mais plutôt à « la totalité de la relation entre les humains et la nature sans être anthropocentrique en soulignant également l''extérieur' (matériel) et l''intérieur' (psychologique, émotif) ».<ref>« Growing up (and old) with Chinese philosopher Li Zehou » (2021).</ref> Li affirme que « le noumène n'est pas la nature, car un univers sans humanité est dénué de sens. Le noumène n'est pas non plus une divinité, car demander aux humains de se prosterner devant un dieu ne correspondrait pas aux notions de 'participation à la transformation et à la nutrition de toutes choses' ou d''établissement du cœur du ciel et de la terre' (''Doctrine du Milieu'', ''Zhongyong''). Il s'ensuit donc que le noumène est l'humanité elle-même ».<ref>Li Zehou, cité dans Zou (2016), p. 88.</ref> '''La sédimentation (積澱, ''jidian'')''' : Le concept de sédimentation est absolument central pour comprendre la structure fondamentale de l'ontologie anthropo-historique de Li Zehou. Ce terme, créé par Li lui-même en raison de l'absence de tout mot existant approprié, décrit « les accumulations et dépôts du social, du rationnel et de l'historique dans l'individu à travers le processus d'humanisation de la nature ».<ref>Li Zehou et Cauvel (2006), cité dans Rošker (2020), p. 14.</ref> Li distingue trois niveaux fondamentaux de sédimentation :<ref>Rošker (2020), p. 14-15.</ref> * La '''sédimentation de l'espèce''' (物種積澱, ''wuzhong jidian'') : le niveau le plus large et le plus profond, incluant les formes universelles communes à tous les êtres humains * La '''sédimentation culturelle''' (文化積澱, ''wenhua jidian'') : le niveau intermédiaire, consistant en formes façonnées par des modèles de pensée et de comportement spécifiques, partagées par les personnes appartenant à des cultures particulières * La '''sédimentation individuelle''' (個體積澱, ''geti jidian'') : le niveau le plus mince et le plus superficiel, consistant en visions du monde intimes, systèmes de valeurs, habitudes, émotions, ainsi que modes individuels de pensée et de ressenti La sédimentation n'est pas un processus statique mais dynamique. Les changements sont les plus rapides au niveau individuel, moyens au niveau culturel, et extrêmement lents au niveau de l'espèce – si lents qu'ils apparaissent comme fixes et immuables du point de vue d'une vie individuelle ou même de plusieurs générations.<ref>Rošker (2020), p. 15.</ref> '''La subjectalité (主體性, ''zhutixing'')''' : Li Zehou a créé le néologisme « subjectalité » (''subjectality'' en anglais) pour distinguer son concept de la simple « subjectivité » (主觀性, ''zhuguanxing''). Alors que la subjectivité est un terme épistémologique se référant à la conscience individuelle, la subjectalité est un terme ontologique se référant à l'être actif et agentif de l'humanité dans son ensemble.<ref>Rošker (2020), p. 20-21.</ref> Comme l'explique un commentateur, « le sujet de la subjectalité n'est pas seulement capable de penser ou de connaître, mais peut également agir, travailler, inventer, produire, se rassembler, coopérer, désirer, ressentir, se souvenir, et ainsi de suite ».<ref>Van den Stock (2020), cité dans Rošker (2020), p. 15.</ref> La subjectalité ne peut pas être réduite au niveau individuel. Elle se réfère d'abord à différents types de communautés humaines – classes, groupes, organisations, nations, États, sociétés – et c'est seulement secondairement qu'elle concerne l'identité de chaque individu.<ref>Rošker (2020), p. 21.</ref> ==== L'humanisation de la nature et la naturalisation des humains ==== '''Le double processus de transformation''' : Li Zehou a développé et complété le concept marxiste d'« humanisation de la nature » (自然的人化, ''ziran de renhua'') avec son propre concept de « naturalisation des humains » (人的自然化, ''ren de ziranhua''). Alors que Marx s'est principalement concentré sur les aspects externes de ce processus – la transformation de la nature physique par le travail humain – Li était davantage intéressé par l'humanisation de la nature intérieure.<ref>Rošker (2020), p. 14-15.</ref> L'humanisation de la nature externe résulte de la création de la civilisation matérielle et donc des structures technico-sociales (工藝社會結構, ''gongyi shehui jiegou''), tandis que la transformation de la nature humaine intérieure génère des formations culturelles-mentales (文化心理結構, ''wenhua xinli jiegou'').<ref>Rogacz, Dawid (2024). « The Philosopher Li Zehou », in ''Li Zehou and Confucian Philosophy'', SUNY Press, p. 435.</ref> '''Les formations culturelles-psychologiques''' : Les formations culturelles-psychologiques se réfèrent aux pouvoirs mentaux que possèdent les individus : cognition, émotion et volonté. De cette façon, la « subjectalité » collective façonne la subjectivité individuelle. D'autre part, puisque la sédimentation « stocke les expériences humaines et façonne la mémoire collective », les subjectivités humaines sont moulées à partir de transformations pratiques du monde objectif.<ref>Chan, Sylvia, citée dans Rogacz (2024), p. 435.</ref> ==== L'esthétique comme ontologie de la philosophie chinoise ==== '''La centralité de l'esthétique''' : Li Zehou considère que la tradition esthétique constitue l'ontologie de la philosophie chinoise, qu'il appelle « ontologie anthropologique », pour souligner l'humanité elle-même comme noumène de la culture chinoise. Différant de la subjectivité transcendantale occidentale, l'humanité ontologique conserve une riche émotion (情, ''qing'') en vivant dans un processus historique concret de la vie d'un individu.<ref>Zou (2016), p. 88.</ref> Comme le résume Karl-Heinz Pohl dans son interview, « lorsque [les intellectuels chinois] ont commencé à s'engager avec la culture occidentale au tournant de 1900, ils ont constaté que l'Occident était façonné par la religion (le christianisme), alors que la Chine était façonnée par l'esthétique. L'esthétique a ainsi été comprise comme l'équivalent fonctionnel de la religion ».<ref>Pohl, Karl-Heinz (2022). « Karl-Heinz Pohl on Confucian philosophy and Chinese aesthetics », interview, ''Chinese Social Sciences Today'', July 12.</ref> '''Le ''Chemin de la beauté'' (美的歷程, ''Mei de licheng'')''' : Publié en 1981, cet ouvrage majeur de Li Zehou retrace l'ensemble de la trajectoire esthétique chinoise depuis les temps anciens jusqu'à la période moderne précoce. Les chapitres commencent par les rites et la musique de l'ère pré-confucéenne, puis s'enchaînent vers l'humanisme confucéen, l'interaction entre les pensées taoïste et confucéenne, la ligne théorique méridionale de l'émotion profonde de Qu Yuan, et les poursuites métaphysiques de l'école bouddhiste Chan, et se terminent par la tendance théorique de la modernité précoce.<ref>Zou (2016), p. 88.</ref> Comparé à d'autres livres chinois qui énumèrent chronologiquement les idées esthétiques des individus, le livre de Li entreprend une investigation philosophique des questions fondamentales de l'esthétique chinoise, telles que les rites, l'humanité, la liberté, l'émotion, la contemplation et le désir.<ref>Zou (2016), p. 88.</ref> ==== La raison pragmatique et la structure émotio-rationnelle ==== '''La raison pragmatique (實用理性, ''shiyong lixing'')''' : Li Zehou croit que la psychologie humaine, tout comme l'humanité ou la « nature humaine », n'est pas fixe ou donnée, mais est plutôt quelque chose caractérisé par des formes développementales changeantes de la raison pragmatique humaine, qui s'est formée sur des millions d'années et continue de s'accumuler et de changer.<ref>Rošker (2020), p. 37.</ref> La raison pragmatique confucéenne est assez différente de la notion kantienne de raison pratique. Elle fonctionne dans l'esprit humain au sein de la structure émotio-rationnelle (情理結構, ''qingli jiegou'') et est fondée sur la substance basée sur l'émotion (情本體, ''qing benti'').<ref>Rošker (2020), p. 37.</ref> '''La structure émotio-rationnelle''' : Ce concept est profondément enraciné dans le monde humain concret. Il est basé sur les conditions humaines actuelles et naît de l'émotionnalité sociale humaine, transformant ces émotions communes générales culturellement intégrées à travers les rites dans le processus de « condensation de la raison » (理性凝聚, ''lixing ningju'') en concepts rationnels de bien et de mal, de juste et de faux.<ref>Rošker (2020), p. 37.</ref> La rationalité de ces concepts gouverne les sentiments subjectifs personnels de chaque membre d'une communauté ; la nature pragmatique de cette rationalité, cependant, est étroitement liée et entrelacée avec les émotions humaines. Dans la vie sociale concrète, ces concepts rationnels peuvent néanmoins se dissoudre – à travers le processus de la « fusion de la raison » (理性融化, ''lixing ronghua'') – dans les cœurs-esprits des gens et ainsi devenir partie intégrante des émotions individuelles.<ref>Rošker (2020), p. 37.</ref> ==== La substance basée sur l'émotion (情本體, ''qing benti'') ==== '''Le cœur de la culture chinoise''' : Li Zehou considère que la substance basée sur l'émotion (''qing benti'') représente le concept central d'une culture de l'optimisme et l'aspect clé du confucianisme.<ref>« Li Zehou's Theory of Emotion as Substance » (n.d.), Sungkyunkwan University.</ref> Pour lui, l'émotion qui se produit dans le monde empirique est le fondement ontologique de base de toute vie humaine.<ref>Li Zehou et Liu Xuyuan (2011), p. 27, cité dans Rošker (2020), p. 112-113.</ref> Li écrit : « La soi-disant substance est la réalité ultime, qui ne peut être davantage questionnée quant à la signification de son existence. Elle dépasse les causalités empiriques. Ce qui dépasse la substance de la psychologie est dieu ou un esprit. Ce qui s'écarte de la psychologie de la substance est la science ou une machine. Par conséquent, la substance ultime et authentique n'est en réalité rien d'autre que la structure de la sensibilité humaine ».<ref>Li Zehou et Liu Xuyuan (2011b), p. 54, cité dans Rošker (2020), p. 113.</ref> '''La vie quotidienne comme sacré''' : Dans la tradition confucéenne réinterprétée par Li, le sacré réside dans la vie séculière. C'est là que nous trouvons la véritable profondeur de la substance. Les relations humaines concrètes – parent-enfant, ami-ami, époux-épouse – sont investies d'une signification quasi-religieuse non pas parce qu'elles mènent à un au-delà transcendant, mais parce qu'elles sont la texture même de l'existence humaine authentique.<ref>Rošker (2020), p. 114-115.</ref> Li peut ainsi écrire : « C'est peut-être la raison pour laquelle les gens peuvent surmonter la mort et conquérir leurs soucis, troubles et peurs. Ce n'est que de cette manière que nous pouvons expérimenter le principe ultime qui est caché dans nos relations quotidiennes au-delà des impératifs moraux, sans un dieu transcendant, dénué de tous esprits aliénés ou de modèles rationnels immobiles. Nous pouvons le trouver dans la chaleur de nos interactions humaines, dans la joie du printemps ».<ref>Li Zehou et Liu Xuyuan (2011b), p. 54, cité dans Rošker (2020), p. 113-114.</ref> ==== La ''mesure'' (度, ''du'') et l'établissement de la beauté ==== '''Les mesures comme art''' : Li définit les « mesures » (度, ''du'') comme prenant le contrôle des contraintes et des possibilités changeantes, pour répondre de manière mesurée et considérée. Les mesures ne sont pas simplement des solutions techniques. Elles ne sont pas non plus simplement un acte, une réponse ou une situation ancrée dans la rationalité.<ref>« Growing up (and old) with Chinese philosopher Li Zehou » (2021).</ref> Les mesures cumulées, qui incluent des interfaces de la nature physique, des objets matériels, de la conscience, des émotions, de l'idéation, et cumulées sur de longues périodes historiques, deviennent sédimentation, un fondement pour une action ultérieure. L'ontologie historique, à son tour, est une accumulation d'art, d'émotions et de mesures. Li affirme même que « les mesures sont en fait l'établissement de la beauté » (立美, ''limei''). Par conséquent, « les mesures sont l'ART ».<ref>« Growing up (and old) with Chinese philosopher Li Zehou » (2021).</ref> ==== La critique et la transformation de Kant ==== '''La transcendantalisation de l'empirique''' : Une des thèses les plus importantes de Li Zehou est que « l'empirique est transformé en transcendantal » (經驗變先驗, ''jingyan bian xianyan''). Ce qui semble être « transcendantal » pour un individu est en réalité une sédimentation, qui a été historiquement acquise à travers l'expérience collective de l'humanité.<ref>Rogacz (2024), p. 435.</ref> En affirmant cela, Li approuve pleinement l'historicisation du transcendantal, si ce n'est l'interprétation du transcendantalisme lui-même comme étant essentiellement une entreprise généalogique. Cela implique cependant d'exclure toute bifurcation entre le conditionné et l'inconditionné, c'est-à-dire ce qui est supposé être indépendant de toute expérience.<ref>Rogacz (2024), p. 435.</ref> '''Le libre arbitre comme formation sédimentée''' : Contrairement à Kant pour qui la raison ou le libre arbitre était indépendant et divorcé du monde phénoménologique, Li comprend le libre arbitre comme une formation mentale et un état psychologique. En tant que tel, il est certainement lié aux neurones à travers lesquels cet état psychologique se produit. Li est convaincu que dans le futur, la neurologie sera capable de révéler l'activité neurologique qui rend les humains différents des animaux et confirmera l'existence de structures mentales complexes façonnées à travers la sédimentation historique et l'éducation individuelle.<ref>Rošker (2020), p. 19-20.</ref> ==== L'influence et l'héritage de Li Zehou ==== '''Un pont entre tradition et modernité''' : L'œuvre de Li Zehou représente une tentative remarquable de construire un pont entre la tradition esthétique chinoise et la modernité. Comme le note un critique, « l'importance de la reconstruction par Li de la tradition esthétique est maintenant reconnue. Ses livres sont, une fois de plus, parmi les plus populaires dans les librairies chinoises ».<ref>Zou (2016), p. 87.</ref> '''La formule "Apprentissage occidental comme substance, apprentissage chinois pour l'application"''' : Li Zehou a inversé la fameuse formule de la fin du XIX<sup>e</sup> siècle « Apprentissage chinois comme substance, apprentissage occidental pour l'application » (中體西用, ''Zhong ti Xi yong'') pour proposer : « Apprentissage occidental comme substance, apprentissage chinois pour l'application » (西體中用, ''Xi ti Zhong yong'').<ref>Li et al. (2024). « Li Zehou's Ideas on Chinese Modernity Revisited », ''Asian Studies'', 12:2, p. 13-34.</ref> Cette formule résume sa position : « Une civilisation matérielle, multiples cultures spirituelles ».<ref>Pohl, Karl-Heinz (2023). « Li Zehou's Major Works on Chinese Aesthetics », p. 14.</ref> La pensée marxiste se réfère aux conditions universelles de notre civilisation matérielle commune (universelle), tandis que les différentes traditions spirituelles et esthétiques – chinoise, occidentale, etc. – représentent la pluralité culturelle qui enrichit l'humanité. '''Un optimisme historique''' : Li était optimiste quant à la progression de l'histoire. Dans son ontologie historique, l'histoire est cumulative. La nature progressive de l'histoire signifie que pour l'humanité dans son ensemble, le développement de la vie matérielle est suivi par la progression de l'éthique et de la moralité.<ref>Rošker (2020), p. 20.</ref> ==== Synthèse : Li Zehou et la renaissance de l'esthétique chinoise ==== Li Zehou a apporté des contributions majeures à la compréhension moderne de l'esthétique chinoise : * Il a montré comment l'esthétique chinoise n'est pas simplement une collection d'idées sur l'art, mais constitue l'ontologie même de la culture chinoise * Il a développé des concepts novateurs – sédimentation, subjectalité, structure émotio-rationnelle, substance basée sur l'émotion – qui permettent de comprendre la spécificité de la tradition chinoise * Il a construit un pont entre la tradition confucéenne et la modernité en intégrant créativement des éléments de la philosophie kantienne et du matérialisme marxiste * Il a démontré que l'esthétique chinoise valorise l'émotion et la relation concrète plutôt que la raison abstraite et la transcendance * Il a proposé une vision dans laquelle l'art et l'esthétique jouent le rôle qu'occupe la religion dans d'autres traditions Comme le résume un commentateur, « à travers les conflits résultant de la vision technico-mondiale apportée par le processus de modernisation chinoise, la signification de la reconstruction par Li de la tradition esthétique est maintenant reconnue. Ses livres sont, une fois de plus, parmi les plus populaires dans les librairies chinoises. Sa philosophie intrigue constamment son public pour qu'il contemple ce qui manque fondamentalement dans la Chine contemporaine et ce qui est le plus précieux dans la culture chinoise ».<ref>Zou (2016), p. 87-88.</ref> L'héritage de Li Zehou continue d'influencer profondément les débats contemporains sur l'identité culturelle chinoise, la modernisation et le dialogue interculturel, offrant une alternative riche et nuancée aux approches purement occidentales de l'esthétique et de la philosophie. === Héritage et actualité === L'esthétique chinoise traditionnelle, loin d'être un héritage figé du passé, continue d'exercer une influence profonde et dynamique sur l'art contemporain, l'architecture, le design et la culture visuelle à l'échelle mondiale au XXI<sup>e</sup> siècle. Cette vitalité témoigne non seulement de la richesse intrinsèque de cette tradition, mais aussi de sa capacité remarquable à se renouveler, à s'adapter et à dialoguer avec la modernité et la globalisation. ==== La persistance des principes esthétiques traditionnels dans l'art contemporain chinois ==== '''L'intégration créative de la tradition''' : Les artistes chinois contemporains ne se contentent pas de reproduire les formes traditionnelles, mais réinterprètent créativement les principes esthétiques classiques dans un contexte moderne. Comme l'observe un article récent, « l'art contemporain chinois est un témoignage de l'héritage durable de l'expression artistique qui a traversé les siècles jusqu'au présent, imprégnant le monde de l'art de son esthétique distinctive ».<ref>« Chinese Art: Traditional & Modern Aesthetics Journey » (2025), ''From Light to Art'', January 27.</ref> Les principes esthétiques traditionnels continuent de façonner l'art contemporain chinois. Par exemple, le principe de ''Shi'' (骨法, méthode des os), ''Qi Yun'' (氣韻, résonance spirituelle), ''Ying'' (應物象形, correspondance à l'objet), ''Jing'' (適合類型, convenance au type), ''Chi'' (傳移摹寫, transmission par copie), et ''Yi'' (經營位置, improvisation) restent des références essentielles pour les artistes contemporains.<ref>« Chinese Art: Traditional & Modern Aesthetics Journey » (2025).</ref> '''Les « trois états » dans les formes artistiques chinoises''' : Une recherche récente en psychologie a identifié une relation tripartite entre l'humanité idéale et la beauté sublime dans les formes artistiques chinoises : l'« état du soi » (自我之境, ''ziwo zhi jing'') qui manifeste le style du sujet individuel, l'« état du non-soi » (無我之境, ''wuwo zhi jing'') qui transcende les limitations du soi, et l'« état vide » (空境, ''kong jing'') qui dépasse même la notion cognitive de « transcender le soi ».<ref>« Threefold relationship between ideal humanity and sublime beauty in Chinese art forms » (2025), ''Frontiers in Psychology'', April 16.</ref> Cette relation tripartite entre l'humanité idéale et la beauté sublime dans l'art chinois peut fournir à la psychologie contemporaine un modèle de recherche et des perspectives uniques sur la prise de conscience de son potentiel personnel, la compréhension de ses émotions et d'autres aspects de l'esprit, et la construction d'objectifs de valeur multiples. ==== Le renouveau de l'esthétique chinoise dans l'architecture contemporaine ==== '''L'architecture néo-chinoise''' : L'architecture contemporaine chinoise représente une fusion remarquable entre les principes traditionnels et l'innovation moderne. Selon un article récent, « l'architecture chinoise est connue pour son équilibre harmonieux entre esthétique, fonctionnalité et symbolisme ».<ref>« Exploring Chinese Architecture: Tradition And Innovation » (2025), ''Hommes Studio'', January 27.</ref> Les éléments clés de l'architecture chinoise qui continuent d'influencer le design contemporain incluent : la symétrie et l'alignement axial (對稱, ''duichen''), le design de cour (四合院, ''siheyuan''), les formes de toit courbées et relevées, l'utilisation de matériaux naturels (pierre, bois, argile), l'intégration avec l'environnement, et l'incorporation du Feng Shui et du symbolisme.<ref>« Exploring Chinese Architecture » (2025).</ref> '''Les architectes contemporains réinterprétant la tradition''' : Plusieurs cabinets d'architecture de premier plan redéfinissent l'architecture chinoise moderne tout en respectant les traditions. André Fu Studio est renommé pour sa capacité à fusionner les influences orientales et occidentales dans le design d'intérieur, créant des espaces sereins et luxueux comme l'illustre The Upper House à Hong Kong. Vector Architects est célèbre pour son attention méticuleuse au contexte et son utilisation de matériaux naturels, comme le démontre la Chapelle de Musique à Ningbo. MAD Architects, dirigé par Ma Yansong, est connu pour ses designs futuristes et organiques qui défient les frontières architecturales conventionnelles, comme le Chaoyang Park Plaza à Pékin.<ref>« Exploring Chinese Architecture » (2025).</ref> Un article récent note que « les bâtiments de style néo-chinois sont profondément intégrés dans la vie contemporaine, présentant une nouvelle perspective sur les valeurs esthétiques et le mode de vie ».<ref>« Neo-Chinese architecture harmonizes modernity and tradition » (2024), ''Global Times'', December 11.</ref> ==== L'esthétique de la vie (生活美學, ''shenghuo meixue'') et la contemporanéité ==== '''Le concept d'esthétique de la vie''' : L'esthétique de la vie (生活美學, ''shenghuo meixue'') est comprise par la plupart des chercheurs chinois comme une façon de relier le monde vécu et l'activité esthétique aujourd'hui.<ref>Li Yuedi (2018). « Contemporary Chinese Living Aesthetics », ''Contemporary Aesthetics'', 16.</ref> Cette approche vise à promouvoir le bonheur et l'expérience vécue. Comme l'explique un article, « aujourd'hui, pour répondre à l'appel de l'esthétique mondiale pour un tournant interculturel, l'esthétique chinoise essaie de s'engager dans le dialogisme mondial, et, avec son esthétique de la vie dans la 'néo-sinité', apporte des contributions importantes à l'expansion bidirectionnelle des esthétiques chinoise et occidentale ».<ref>Li Yuedi (2018).</ref> '''La reconstruction de la sinité (中國性, ''Zhongguoxing'')''' : Depuis 1978, l'art contemporain chinois a traversé un processus allant de la dé-sinisation à la re-sinisation, c'est-à-dire un processus historique allant de la dé-contextualisation à la re-contextualisation. Aujourd'hui, l'art chinois contemporain se développe de plus en plus en synchronisation avec le monde. En même temps, la valeur de la construction de la sinité se révèle de plus en plus.<ref>Li Yuedi (2018).</ref> L'objectif est de puiser dans les ressources culturelles traditionnelles afin qu'elles puissent être présentées sous forme de produits et d'industries culturels. Retourner à l'esthétique de la vie est le chemin le plus pratique et le plus court pour reconstruire la néo-sinité. ==== L'influence mondiale de l'esthétique chinoise ==== '''Le dialogue interculturel''' : L'esthétique chinoise exerce une influence croissante sur le discours esthétique mondial. Comme le note un article, « dans le contexte de la mondialisation contemporaine, l'art, en tant que médium qui traverse les frontières culturelles, devient un outil important pour que les gens communiquent et s'expriment au-delà des restrictions géographiques et linguistiques ».<ref>« Iconography from A Cross-cultural Perspective: Comparison of Expressions in Chinese and European Art » (2023), ''Art and Humanities Research'', December 21.</ref> La diversité des expressions visuelles et des concepts esthétiques dans différents contextes culturels apporte un charme unique et une richesse à la création artistique. La Chine et l'Europe, en tant que deux civilisations avec de longues histoires et de profondes traditions culturelles, ont des créations et des expressions riches dans le domaine de l'art. '''L'art abstrait expressionniste et l'esthétique chinoise''' : Un exemple frappant de l'influence chinoise sur l'art mondial est la relation entre l'expressionnisme abstrait et l'esthétique chinoise. Comme l'observe un article, « en tant qu'école d'art représentative du XX<sup>e</sup> siècle en Occident, l'expressionnisme abstrait a de manière inattendue une caractéristique artistique très distinctive de la Chine ».<ref>« On Chinese Aesthetics of Abstract Expressionism Art » (2023), ''Highlights in Art and Design'', June 25.</ref> En termes d'environnement objectif, le dialogue artistique entre la Chine et l'Occident au XX<sup>e</sup> siècle a été promu vers le domaine de la philosophie métaphysique. L'intérêt des artistes occidentaux pour l'art oriental a dépassé leur compréhension superficielle de leurs traits de pinceau uniques, et l'art abstrait est devenu le meilleur pont culturel pour communiquer entre l'Est et l'Ouest. ==== Les défis de la modernité et les réponses de l'esthétique chinoise ==== '''La critique de la modernité occidentale''' : L'esthétique chinoise traditionnelle offre des ressources importantes pour critiquer certains aspects problématiques de la modernité occidentale. Comme le souligne Guo Qiyong, « actuellement, il y a des problèmes avec le développement de la révolution technologique et d'Internet, des problèmes impliquant l'éthique de la vie, l'éthique environnementale, l'éthique familiale, l'éthique communautaire, l'éthique d'Internet et l'éthique spatiale, etc., et même l'éthique mondiale doit être établie ».<ref>Guo Qiyong (2022). ''The Characteristics of Chinese Cultural Spirit'', Springer, p. 116-117.</ref> M. Tang Junyi a dit un jour que la situation absurde à laquelle sont confrontés les gens modernes est que les gens sont sans poursuite ultime, esprit terre-à-terre, relations personnelles harmonieuses et esprit du vrai soi. L'esprit humaniste chinois, en particulier l'esprit humaniste confucéen, peut sauver les gens d'une telle situation. '''Les ressources spirituelles pour la mondialisation''' : Le confucianisme peut fournir les ressources spirituelles et la sagesse humaniste suivantes pour la mondialisation économique : la renaissance de la civilisation des rites et de la musique pourrait élargir davantage l'espace culturel, accumuler du capital social et culturel et nourrir l'intelligence émotionnelle des gens. Il est d'une grande importance d'observer les valeurs fondamentales confucéennes telles que la bienveillance (仁, ''ren''), la justice (義, ''yi''), la bienséance (禮, ''li''), la sagesse (智, ''zhi'') et la confiance (信, ''xin''). « Il se tient bien et il fait tenir les autres bien aussi. Il cherche la lumière pour lui-même et il éclaire les autres. C'est la voie vers la bienveillance. Ne fais pas aux autres ce que tu ne voudrais pas qu'on te fasse. Respecter le travail et profiter de la compagnie. » Ils peuvent jouer des rôles positifs dans la construction de l'éthique mondiale moderne, de l'éthique communautaire, de l'éthique familiale, de l'éthique professionnelle et des relations entre les personnes.<ref>Guo Qiyong (2022), p. 117.</ref> Des concepts tels que « l'homme et le monde et toutes choses sont un » (天人合一, ''tian ren he yi''), « les gens sont mes frères et toutes choses sont mes semblables » peuvent aider à construire une nouvelle éthique écologique et environnementale ainsi qu'une stratégie de développement durable. ==== L'art environnemental chinois contemporain ==== '''L'influence du taoïsme et du confucianisme''' : L'art environnemental chinois contemporain s'inspire profondément des traditions taoïste et confucéenne. Comme l'explique un article récent, « l'art environnemental chinois, influencé par le taoïsme et le confucianisme, se concentre sur l'équilibre entre l'homme et la nature ».<ref>« Contemporary Chinese Environmental Art and Cross-cultural Communication » (2025), ''European Journal of Arts, Humanities and Social Sciences''.</ref> L'évolution de l'éco-art dans le contexte chinois est influencée par les traditions socio-historiques de la nation, auxquelles le taoïsme et le confucianisme étaient principalement associés. Alors que le début de l'éco-art dans d'autres parties du monde était une solution employée pour résoudre les problèmes écologiques, la vision du monde chinoise de l'éco-art est basée sur des dogmes philosophiques séculaires d'équilibre entre les hommes et la nature.<ref>« Contemporary Chinese Environmental Art » (2025).</ref> En particulier, les paysages peints à l'encre sont un sous-genre artistique commun dans les cultures chinoises où les gens sont représentés à une échelle plus petite dans le cadre de la nature, reflétant le grand pouvoir de la nature et l'unité de tous les êtres. ==== La porcelaine chinoise et l'innovation fonctionnelle ==== '''La transformation de l'esthétique traditionnelle''' : La porcelaine chinoise, l'un des symboles les plus reconnaissables de la culture chinoise, continue d'évoluer au XXI<sup>e</sup> siècle. Un article récent examine « la transformation de l'esthétique et du style de la porcelaine chinoise aux XX<sup>e</sup> et XXI<sup>e</sup> siècles en termes d'innovation fonctionnelle ».<ref>« Research on functional innovations in Chinese porcelain: from tradition to modernity » (2025), ''Culture and Arts in the Modern World'', March 31.</ref> L'étude considère les nouvelles fonctions de la porcelaine chinoise comme un phénomène complexe. L'innovation incorpore trois aspects : le développement technologique, les changements de significations culturelles et l'adaptation au marché. Elle montre comment les méthodes artisanales traditionnelles et les techniques éprouvées de décoration et de création de forme sont remplacées par de nouvelles. Dans les nouvelles méthodes de travail avec les produits, les technologies numériques et les matériaux modernes sont combinés avec l'héritage historique. '''L'intégration des motifs traditionnels dans le design moderne''' : L'application et l'innovation des motifs traditionnels chinois dans les illustrations modernes, le design de produits et d'autres domaines démontrent la vitalité continue de l'esthétique traditionnelle. Comme le note un article, « sur la base des connotations historiques et des caractéristiques stylistiques des motifs traditionnels chinois, il discute de la connotation plus profonde, des couleurs et des motifs des motifs traditionnels dans les illustrations modernes ».<ref>« Application and Innovation of Traditional Chinese Patterns in Modern Illustrations » (2022), ''BCP Social Sciences & Humanities'', October 17.</ref> Cet article vise à trouver une meilleure façon de diffuser les motifs traditionnels chinois, un symbole culturel avec des caractéristiques nationales uniques, en analysant la méthodologie de combinaison du « traditionnel » avec le « moderne ». ==== Les industries culturelles et créatives ==== '''Le renouveau des motifs traditionnels''' : La Chine connaît actuellement un renouveau vibrant de l'esthétique néo-chinoise qui prend de l'ampleur, mélangeant le riche patrimoine de la Chine avec la créativité contemporaine, offrant une esthétique unique.<ref>« Neo-Chinese aesthetics combines traditional techniques with modern design » (2025), ''Global Times'', June 11.</ref> Ce phénomène se manifeste dans de nombreux domaines : les jeux vidéo (comme les skins du Nouvel An lunaire dans League of Legends qui explorent l'esthétique chinoise à travers des éléments visuels), la mode, le design de produits, et même l'animation. L'industrie culturelle chinoise réussit à transformer les ressources culturelles traditionnelles en produits contemporains attractifs. '''L'exposition "Root in Profound Culture"''' : Une exposition importante au Shenzhen Museum of Contemporary Art and Urban Planning a invité 31 maîtres d'art contemporain et jeunes artistes à présenter leurs œuvres de transformation moderne de la culture traditionnelle dans quatre zones d'exposition : « Wan Wu Zi Bin » (embrasser toutes choses), « Li Yun Da Tong » (harmonie par le rituel), « Chong Ya Chu Fu » (élégance sur vulgarité), et « Jian Ji Shang Yi » (compétence et art).<ref>« The emerging aesthetic and philosophical identity of Chinese contemporary art » (2023), ''ADF Web Magazine'', August 25.</ref> Cette exposition thématique met en évidence l'évolution innovante de l'art contemporain à l'ère moderne. Elle dépeint vivement le dynamisme actuel de la culture chinoise, mettant en valeur l'impact constructif de l'art contemporain dans l'avancement de la propagation et de la croissance de la culture traditionnelle. ==== Les défis et les perspectives ==== '''La tension entre tradition et modernité''' : Malgré ces développements positifs, l'héritage et l'actualisation de l'esthétique chinoise font face à plusieurs défis. Le processus de modernisation rapide et d'urbanisation en Chine a parfois conduit à une perte de savoir-faire traditionnel et à une commercialisation excessive des formes culturelles. Comme le souligne un article, « la Chine possède une culture profonde et sophistiquée enracinée dans les brumes du temps, qui travaille dur pour ré-émerger de l'épuisement de l'ère industrielle avec une identité contemporaine revitalisée ».<ref>« The emerging aesthetic and philosophical identity » (2023).</ref> '''Le rôle de l'éducation''' : Pour assurer la transmission et le renouvellement de l'esthétique chinoise, l'éducation joue un rôle crucial. Guo Qiyong recommande : « Premièrement, nous devrions clarifier et critiquer les vues spécieuses sur le confucianisme depuis le Mouvement du 4 mai 1919, les années 1950, et surtout depuis la Révolution culturelle. Deuxièmement, nous devrions incorporer le confucianisme dans notre éducation et notre sensibilisation sociale en commençant par l'éducation primaire. L'apprentissage des Quatre Livres devrait être inclus dans l'enseignement secondaire. Le confucianisme et la culture chinoise devraient être introduits dans les entreprises et les communautés pour construire l'éthique d'entreprise et l'éthique professionnelle, pour élever la culture sociale ».<ref>Guo Qiyong (2022), p. 114-115.</ref> '''Le dialogue des civilisations''' : Dans le contexte de la mondialisation, l'esthétique chinoise peut jouer un rôle important dans le dialogue des civilisations. Comme l'affirme l'initiative « Une Ceinture, Une Route », la Chine cherche à promouvoir les échanges culturels tout en maintenant sa propre identité culturelle. Le philosophe Tu Weiming a souligné l'importance du concept de « Chine culturelle » (文化中國, ''wenhua Zhongguo''), qui transcende les frontières géographiques et politiques pour englober tous ceux qui participent à la tradition culturelle chinoise. Cette vision permet d'envisager l'esthétique chinoise non pas comme un patrimoine figé, mais comme une tradition vivante et en constante évolution.<ref>Tu Weiming, cité dans Guo Qiyong (2022), p. 116.</ref> ==== Synthèse : vers une esthétique chinoise du XXI<sup>e</sup> siècle ==== L'héritage et l'actualité de l'esthétique chinoise démontrent que : * L'esthétique chinoise n'est pas un musée de formes anciennes, mais une tradition vivante capable de se renouveler et de répondre aux défis contemporains * Les principes esthétiques traditionnels (harmonie, équilibre yin-yang, vide et plein, souffle vital, etc.) restent pertinents et peuvent être créativement transformés pour l'époque moderne * L'esthétique chinoise offre des ressources importantes pour critiquer certains excès de la modernité occidentale (anthropocentrisme, rationalisme instrumental, fragmentation) * Le dialogue entre l'esthétique chinoise et les traditions esthétiques mondiales enrichit la compréhension humaine de la beauté et de l'art * L'avenir de l'esthétique chinoise réside dans sa capacité à maintenir son identité distincte tout en s'ouvrant au dialogue interculturel Comme le conclut un observateur, « l'art contemporain chinois, dans son mariage magnifique de l'esthétique traditionnelle et moderne, témoigne de l'esprit résilient de la culture chinoise. Il continue son voyage mystique, embrassant gracieusement les murmures de la sagesse ancienne, les cris de la modernité, et les mélodies infinies qui se trouvent entre les deux ».<ref>« Chinese Art: Traditional & Modern Aesthetics Journey » (2025).</ref> L'esthétique chinoise du XXI<sup>e</sup> siècle sera ainsi caractérisée par une triple fidélité : fidélité à ses racines philosophiques et spirituelles, fidélité aux exigences de la contemporanéité, et fidélité à sa vocation universelle de contribuer au patrimoine esthétique de l'humanité tout entière. == Notes et références == {{references|colonnes=2}} == Bibliographie == === Sources primaires === ==== Textes classiques chinois ==== * '''Confucius''', ''Analectes'' (論語, ''Lunyu''), traductions françaises multiples (notamment Anne Cheng, Paris, Seuil, 1981) * '''Laozi''', ''Daode Jing'' (道德經, ''Tao Te Ching''), traductions françaises multiples * '''Zhuangzi''', ''Zhuangzi'' (莊子), traduction Jean Levi, Paris, Albin Michel, 2006 * ''Yi Jing'' (易經, ''Livre des Mutations''), traduction Cyrille Javary, Paris, Albin Michel, 2002 * ''Liji'' (禮記, ''Livre des Rites''), traductions multiples * ''Zhongyong'' (中庸, ''La Doctrine du Milieu''), in ''Les Quatre Livres'' * ''Commentaire de Zuo'' (左傳, ''Zuozhuan'') * '''Xunzi''', ''Xunzi'' (荀子) * '''Mencius''', ''Mencius'' (孟子, ''Mengzi'') * '''Dong Zhongshu''', ''Chunqiu fanlu'' (春秋繁露, ''Luxuriantes rosées des Annales des Printemps et Automnes'') * '''Wang Chong''', ''Lunheng'' (論衡, ''Disquisitions''), vers 76-84 de notre ère * '''Xu Shen''', ''Shuowen Jiezi'' (說文解字, ''Explication des caractères et analyse des graphies''), Yuelu Academy Press, 2006 [édition originale : dynastie Han] * '''Liu Xie''', ''Wenxin Diaolong'' (文心雕龍, ''L'Esprit littéraire et la sculpture du dragon''), vers 501-502 * '''Zhong Rong''', ''Shipin'' (詩品, ''Classement de la poésie''), 468-518 * '''Sikong Tu''', ''Ershisi Shipin'' (二十四詩品, ''Vingt-quatre styles de poésie''), 837-908 * '''Xie He''', ''Liufa'' (六法, ''Les Six Principes''), dans ''Guhua Pinlu'' (古畫品錄), vers 550 * '''Wu Ke''', ''Zanghai Shihua'' (藏海詩話, ''Wu Zanghai sur la poésie''), dynastie Song * '''Wang Shizhen''', ''Huacao Mengshi'' (花草夢詩), 1634-1711 * '''Duan Yucai''', ''Explication du Shuowen Jiezi'', section 4.1, 1735-1835 * ''Sutra du Cœur'' (心經, ''Xin Jing'') * ''Sutra du Diamant'' (金剛經, ''Jingang Jing'') * ''Sutra du Lotus'' (法華經, ''Fahua Jing'') === Ouvrages de référence === ==== En français ==== * '''Cheng, Anne''' (2002). ''Histoire de la pensée chinoise'', Paris, Éditions du Seuil, 696 p. * '''Granet, Marcel''' (1934, réédité 1988). ''La pensée chinoise'', Paris, Albin Michel, « Bibliothèque de l'Évolution de l'Humanité », 568 p. * '''Jullien, François''' (2015). ''De l'Être au Vivre : Lexique euro-chinois de la pensée'', Paris, Gallimard, « Bibliothèque des Idées », 280 p. * '''Jullien, François''' (2003). ''La Grande Image n'a pas de forme, ou Du non-objet par la peinture'', Paris, Seuil, « L'Ordre philosophique », 384 p. [édition anglaise : University of Chicago Press, 2022] ==== En anglais - Ouvrages monographiques ==== * '''Guo, Qiyong''' (2022). ''The Spirit of Chinese Confucianism'', Singapore, Springer Nature, 550 p. * '''Guo, Qiyong''' (2022). ''The Characteristics of Chinese Cultural Spirit'', trad. Ran Tao, Kunming Fan et Zhou Xu, Singapore, Springer Nature, 210 p. * '''Li, Deshun''' (2022). ''The Construction of Value Philosophy in Contemporary China'', Singapore, Springer Nature * '''Ma, Tianxiang''' (2020). ''History of the Development of Chinese Chan Thought'', Singapore, Springer Nature, 440 p. * '''Qi, Zhixiang''' (2024). ''The Spirit of Traditional Chinese Aesthetics'', Singapore, Springer Nature, 245 p. * '''Rošker, Jana S.''' (2020). ''Becoming Human: Li Zehou's Ethics'', Leiden, Brill, « Modern Chinese Philosophy » vol. 20, xiv + 332 p. * '''Vermander, Benoît''' (2022). ''The Encounter of Chinese and Western Philosophies'', Leiden, Brill, 450 p. * '''Wang, Yueqing, Bao, Qinggang, et Guan, Guoxing''' (2020). ''History of Chinese Philosophy Through Its Key Terms'', trad. Shuchen Xiang, Singapore, Springer Nature, 450 p. * '''Wu, Genyou''' (éd.) (2024). ''The Civilization of China and the Civilizations of the World'', trad. Fei Ma, Singapore, Springer Nature, 280 p. ==== Articles dans des revues académiques ==== * '''Cai, Zong-qi''' (2017). « Emotion, Patterning, and Visuality in Chinese Literary Thought », ''Journal of Chinese Literary Criticism'', 6:1, p. 1-25 * '''Falkenhausen, Lothar von''' (1996). « The Concept of Wen in the Ancient Chinese Ancestral Cult », ''Chinese Literature: Essays, Articles, Reviews'', 18, p. 1-22 * '''Gu, Ming Dong''' (2003). « Aesthetic Suggestiveness in Chinese Thought », ''The Journal of Aesthetics and Art Criticism'', 61:2, p. 143-155 * '''Guan, Yongqiang''' (2024). « Aesthetic conceptions and cultural symbols in traditional Chinese painting », ''Trans/Form/Ação'', Marília, 47:4, p. 1-22 * '''Li, Yuedi''' (2018). « Contemporary Chinese Living Aesthetics and Confucian Aesthetics as a New Direction », ''Contemporary Aesthetics'', vol. 16, novembre 2018 * '''Man, Eva Kit Wah''' (2013). « Influence of Global Aesthetics on Chinese Aesthetics: The Adaptation of Moxie », ''Contemporary Aesthetics'', vol. 11 * '''Sernelj, Teja''' (2020). « Different Approaches to Modern Art and Society: Li Zehou versus Xu Fuguan », ''Asian Studies'', 8:1, p. 77-98 * '''Sun, Chao''' (2018). « An Interpretation of "Xingwei" », ''Theoretical Studies in Literature and Art'', 38:3, p. 151-159 * '''Tang, Yanfang''' (2014). « Yi Jing and Understanding Chinese Poetry », ''Intercultural Communication Studies'', XXIII:1, p. 189-206 * '''Yang, Zhu''' (2011). « The Aesthetic Standard of Wen: A Comparative Study of Chinese and Western Early Artworks », ''Asian Studies'', II:2, p. 37-67 * '''Yang, Zhu''' (2015). « Poetic Taste and Tasting Poetry », in ''Linking Ancient and Contemporary: Bridges across the East-West Divide'', Edizioni Ca' Foscari, p. 299-316 * '''Yu, Kar Fai Timothy''' (2023). « Cinematic ideorealm and cinema following Dao: theorizing China's film aesthetics with François Jullien and Gilles Deleuze », ''Screen'', 64:4, Winter 2023, p. 462-477 * '''Zou, Hui''' (2016). « Li Zehou. The Chinese Aesthetic Tradition », ''Montreal Architectural Review'', vol. 3, p. 87-88 ==== Travaux sur Li Zehou ==== * '''Li, Zehou''' (1979). ''Pipan zhexue de pipan'' (批判哲學的批判, ''Critique de la philosophie critique''), Beijing * '''Li, Zehou''' (1981). ''Mei de licheng'' (美的歷程, ''Le Chemin de la beauté''), Beijing * '''Li, Zehou''' (1989). ''Huaxia meixue'' (華夏美學, ''La tradition esthétique chinoise''), Beijing * '''Li, Zehou et Cauvel, Jane''' (2006). ''Four Essays on Aesthetics'', Lexington Books * '''Li, Zehou et Liu, Xuyuan''' (2011a, 2011b). Divers ouvrages sur la philosophie esthétique * '''Li et al.''' (2024). « Li Zehou's Ideas on Chinese Modernity Revisited », ''Asian Studies'', 12:2, p. 13-34 * '''Pohl, Karl-Heinz''' (2023). « Li Zehou's Major Works on Chinese Aesthetics », Confucius Institute Trier, 14 p. * '''Rogacz, Dawid''' (2024). « The Philosopher Li Zehou », in ''Li Zehou and Confucian Philosophy'', Albany, SUNY Press, p. 429-450 ==== Ouvrages de Karl-Heinz Pohl ==== * '''Pohl, Karl-Heinz''' (2012). « Chinese and Western Aesthetics », University of Trier, Department of Sinology, 12 p. * '''Pohl, Karl-Heinz''' (2017). « Chinese Aesthetics and Kant », in ''A Companion to Comparative Philosophy'', Blackwell, p. 433-452 * '''Pohl, Karl-Heinz''' (2022). « Karl-Heinz Pohl on Confucian philosophy and Chinese aesthetics », entretien, ''Chinese Social Sciences Today'', 12 juillet 2022 ==== Ouvrages généraux ==== * '''Collingwood, R. G.''' (1938, trad. chinoise 1987). ''Les Principes de l'art'' (藝術原理, ''Yishu Yuanli''), trad. Wang Zhiyuan et Chen Huazhong, Beijing, Chinese Social Science Press, 450 p. * '''Owen, Stephen''' (1992). ''Readings in Chinese Literary Thought'', Cambridge, Harvard University Asia Center, 600 p. * '''Qian, Mu''' (1988). ''An Introduction to the History of Chinese Culture'', Shanghai, Shanghai Sanlian Bookstore, 450 p. * '''Shen, Jiahui''' (2023). ''Wen and Zhi as a Conceptual Pair in Early Chinese Thought'', Master Thesis, Ithaca, Cornell University, 85 p. * '''Zang, Kehe''' (1990). ''Caractères chinois et mentalité esthétique'' (漢字文學與審美心理, ''Hanzi Wenxue He Shenmei Xinli''), Shanghai, Xuelin Press, p. 13 === Articles récents et ressources en ligne === * « A unique facet of Chinese aesthetics » (2024), ''Chinese Social Sciences Net'', 26 août 2024 * « Aesthetic Comparison of Chinese and Western Landscape Culture » (2018), ''Advances in Social Science, Education and Humanities Research'', vol. 284 * « Application and Innovation of Traditional Chinese Patterns in Modern Illustrations » (2022), ''BCP Social Sciences & Humanities'', vol. 20, 17 octobre 2022 * « Between emptiness and reality: from the white space in Chinese painting to the philosophy of form in western art » (2025), ''Trans/Form/Ação'', Marília, vol. 48 * « Chinese Art: Traditional & Modern Aesthetics Journey » (2025), ''From Light to Art'', 27 janvier 2025 * « Chinese Cloud and Thunder Patterns: Yun Lei Wen » (2024), ''Chinese Showcase'', 27 mai 2024 * « Confucian and Daoist Aesthetics » (2024), ''Asian Studies'', vol. 12 * « Contemporary Chinese Environmental Art and Cross-cultural Communication » (2025), ''European Journal of Arts, Humanities and Social Sciences'', vol. 1 * « Exploring Chinese Architecture: Tradition And Innovation » (2025), ''Hommes Studio Journal'', 27 janvier 2025 * « Growing up (and old) with Chinese philosopher Li Zehou » (2021), ''Think China'', 18 novembre 2021 * « Iconography from A Cross-cultural Perspective: Comparison of Expressions in Chinese and European Art » (2023), ''Art and Humanities Research'', vol. 2, 21 décembre 2023 * '''Key Concepts in Chinese Thought and Culture''' (2021), « Jing », « Jingjie », « Yijing », chinesethought.cn, Pékin, China Association for the Study of Chinese History of Philosophy * « Neo-Chinese aesthetics combines traditional techniques with modern design » (2025), ''Global Times'', 11 juin 2025 * « Neo-Chinese architecture harmonizes modernity and tradition » (2024), ''Global Times'', 11 décembre 2024 * « On Chinese Aesthetics of Abstract Expressionism Art » (2023), ''Highlights in Art and Design'', vol. 4:2, 25 juin 2023 * « Philosophical implications of the civilization imagery in ancient China » (2024), ''Guangming Daily'', 25 juin 2024 * « Research on functional innovations in Chinese porcelain: from tradition to modernity » (2025), ''Culture and Arts in the Modern World'', 31 mars 2025 * « The Birth of Artistic Conception in China » (2017), ''International Journal of Regional and Local History'', 12:2, 2 juillet 2017 * « The Embodiment of the Idea of the 'Golden Mean' in the Aesthetics of Confucius » (2024), ''History of Philosophy & Logic'', 45:4, 31 octobre 2024 * « The emerging aesthetic and philosophical identity of Chinese contemporary art » (2023), ''ADF Web Magazine'', 25 août 2023 * « Threefold relationship between ideal humanity and sublime beauty in Chinese art forms » (2025), ''Frontiers in Psychology'', vol. 16, 16 avril 2025 === Philosophes occidentaux cités === * '''Aristote''', ''Poétique'', trad. J. Hardy, Paris, Les Belles Lettres, 1932 * '''Heidegger, Martin''' (1927). ''Sein und Zeit'' (''Être et Temps''), Tübingen, Max Niemeyer Verlag [trad. fr. Emmanuel Martineau, Paris, Authentica, 1985] * '''Kant, Immanuel''' (1790). ''Kritik der Urteilskraft'' (''Critique de la faculté de juger''), Berlin [trad. fr. Alain Renaut, Paris, Flammarion, 1995] * '''Platon''', ''Hippias Majeur'' (''Grand Hippias''), in ''Œuvres complètes'', trad. Léon Robin, Paris, Gallimard, « Bibliothèque de la Pléiade », 1950 * '''Saint Thomas d'Aquin''' (XIIIe siècle), ''Summa Theologica'', écrits sur l'esthétique * '''Sartre, Jean-Paul''' (1943). ''L'Être et le Néant'', Paris, Gallimard == Voir aussi == {{Début de colonnes|nombre=3}} === Philosophies et courants chinois === * [[Confucianisme]] * [[Taoïsme]] * [[Bouddhisme Chan]] * [[Néo-confucianisme]] * [[École des Légistes]] * [[Mohisme]] * [[Xuanxue]] (Étude du mystère) * [[Philosophie chinoise]] * [[Pensée chinoise]] === Concepts philosophiques clés === * [[Dao]] (道) * [[De (vertu)]] (德) * [[Qi]] (氣, souffle vital) * [[Yin et Yang]] * [[Wu wei]] (無為, non-agir) * [[Ziran]] (自然, spontanéité naturelle) * [[Ren]] (仁, bienveillance) * [[Li (rituel)]] (禮) * [[Xin]] (心, cœur-esprit) * [[Tian]] (天, Ciel) === Concepts esthétiques === * [[Yijing (conception artistique)]] (意境) * [[Qi yun]] (氣韻, résonance spirituelle) * [[Chuanshen]] (傳神, transmettre l'esprit) * [[Xiangwai]] (象外, au-delà de l'image) * [[Fenggu]] (風骨, os et vent) * [[Xuanmiao]] (玄妙, mystère et subtilité) * [[Wei (saveur)]] (味) * [[Wen (culture)]] (文) * [[Shanshui]] (山水, montagnes et eaux) * [[Jing (royaume)]] (境) === Arts traditionnels chinois === * [[Calligraphie chinoise]] * [[Peinture chinoise]] * [[Peinture de lettrés]] (文人畫) * [[Peinture de paysage chinoise]] * [[Poésie chinoise]] * [[Poésie Tang]] * [[Musique chinoise]] * [[Opéra chinois]] * [[Architecture chinoise]] * [[Jardin chinois]] * [[Céramique chinoise]] * [[Porcelaine chinoise]] === Figures majeures === ==== Philosophes classiques ==== * [[Confucius]] * [[Laozi]] * [[Zhuangzi]] * [[Mencius]] * [[Xunzi]] * [[Wang Bi]] * [[Guo Xiang]] ==== Théoriciens de l'art ==== * [[Xie He]] (謝赫) * [[Zhang Yanyuan]] (張彥遠) * [[Guo Xi]] (郭熙) * [[Su Shi]] (蘇軾) * [[Dong Qichang]] (董其昌) * [[Shi Tao]] (石濤) ==== Critiques littéraires ==== * [[Liu Xie]] (劉勰) * [[Zhong Rong]] (鍾嶸) * [[Sikong Tu]] (司空圖) * [[Yan Yu]] (嚴羽) * [[Wang Shizhen]] (王士禎) * [[Wang Guowei]] (王國維) === Philosophes modernes === * [[Li Zehou]] (李澤厚) * [[Tang Junyi]] (唐君毅) * [[Mou Zongsan]] (牟宗三) * [[Xu Fuguan]] (徐復觀) * [[Feng Youlan]] (馮友蘭) * [[Liang Shuming]] (梁漱溟) === Sinologues occidentaux === * [[François Jullien]] * [[Anne Cheng]] * [[Marcel Granet]] * [[Joseph Needham]] * [[Karl-Heinz Pohl]] * [[Benoît Vermander]] === Esthétique comparée === * [[Esthétique]] * [[Esthétique occidentale]] * [[Esthétique japonaise]] * [[Philosophie de l'art]] * [[Théorie de l'art]] * [[Histoire de l'art]] * [[Mimesis]] * [[Catharsis]] * [[Sublime (esthétique)]] === Thèmes connexes === * [[Culture chinoise]] * [[Civilisation chinoise]] * [[Pensée de l'Asie orientale]] * [[Bouddhisme zen]] * [[Wabi-sabi]] * [[Ikebana]] * [[Art asiatique]] * [[Sinologie]] * [[Études chinoises]] * [[Dialogue interculturel]] {{Fin de colonnes}} === Liens externes === * [https://www.chinesethought.cn/EN Key Concepts in Chinese Thought and Culture] (ressource académique en ligne) * [https://plato.stanford.edu/entries/aesthetic-concept/ Stanford Encyclopedia of Philosophy - Aesthetic Concepts] * [https://www.iep.utm.edu/chinese-aesthetics/ Internet Encyclopedia of Philosophy - Chinese Aesthetics] {{autocat}} m12mapnji5gb2kpxk6fb53rgm0ltbea Dictionnaire de philosophie/Causalité 0 83045 768471 768230 2026-06-24T04:38:52Z PandaMystique 119061 /* Spinoza et la nécessité absolue de la nature */ 768471 wikitext text/x-wiki {{DicoPhilo|Causalité|lecture=oui}} La causalité désigne le rapport par lequel un phénomène (la cause) produit ou engendre un autre phénomène (l'effet). Cette notion joue un rôle fondateur dans la connaissance scientifique et la compréhension philosophique du monde. Pourtant, loin d'être une évidence, la causalité pose des problèmes théoriques considérables qui traversent l'histoire de la philosophie, depuis l'Antiquité jusqu'aux débats contemporains. Comprendre ce qu'est une cause, comment elle agit, si elle implique nécessité ou simple régularité, si elle existe objectivement ou n'est qu'une construction de l'esprit : autant de questions qui font de la causalité un des concepts les plus discutés de la philosophie. ==Le problème de la nature de la causalité== ===La causalité comme production nécessaire=== Le rapport entre cause et effet ne se réduit pas à une simple succession d'événements dans le temps. La tradition métaphysique qui s'étend d'Aristote à Leibniz conçoit la relation causale comme impliquant un lien de nécessité : l'effet découle nécessairement de sa cause, et non pas seulement à titre de fait constaté. Cette conception fait de la causalité le fondement même de l'intelligibilité du monde, puisque comprendre un phénomène revient à saisir sa cause, c'est-à-dire la raison qui explique pourquoi il ne pouvait pas ne pas se produire. Contre l'idée que l'univers serait un chaos d'événements contingents et arbitraires, la métaphysique classique affirme que tout ce qui existe possède une raison d'être, une cause qui en rend compte. ====Les fondements scolastiques : Thomas d'Aquin et la causalité efficiente==== La pensée médiévale, en particulier dans sa version thomiste, élabore une théorie de la causalité fondée sur la distinction entre l'essence et l'existence. Pour Thomas d'Aquin, les êtres créés se caractérisent par le fait que leur essence (ce qu'ils sont) ne contient pas en elle-même la raison de leur existence (le fait qu'ils soient). Un triangle possède une essence déterminée – être une figure plane à trois côtés –, mais cette essence ne nous dit pas si des triangles existent effectivement dans la réalité. Cette séparation entre essence et existence signifie que les créatures sont ontologiquement contingentes : elles pourraient ne pas exister. Or, si quelque chose existe sans que son essence n'implique nécessairement son existence, il faut une cause extérieure qui lui confère l'être. Dans la ''Somme théologique'', Thomas expose la « deuxième voie » de démonstration de l'existence de Dieu à partir de la causalité efficiente<ref>Thomas d'Aquin, ''Somme théologique'', I, q. 2, a. 3</ref>. Nous constatons dans le monde sensible un ordre de causes efficientes : tel événement produit tel autre, qui à son tour en produit un troisième. Mais aucune chose ne peut être cause efficiente d'elle-même, car elle devrait alors être antérieure à elle-même, ce qui constitue une contradiction. Il existe donc une série de causes efficientes où chaque maillon dépend du précédent. Thomas précise qu'il ne s'agit pas d'une série temporelle remontant indéfiniment dans le passé (une chaîne « horizontale »), mais d'une série de causes hiérarchiquement ordonnées et simultanées (une chaîne « verticale »). L'exemple qu'il propose illustre cette structure : la main meut le bâton qui meut la pierre. Ces trois causes agissent en même temps, mais dans un ordre de dépendance ontologique. La main possède en elle-même le pouvoir de mouvoir ; le bâton ne meut que parce qu'il est mû par la main ; la pierre ne se meut que parce qu'elle est mue par le bâton. Le bâton et la pierre sont des causes instrumentales, subordonnées à une cause principale qui possède intrinsèquement l'efficacité causale. Cette analyse conduit Thomas à affirmer qu'une régression infinie de causes instrumentales est impossible. Si chaque cause dans la série ne fait que transmettre une causalité qu'elle reçoit d'une autre, et qu'aucune ne possède par elle-même le pouvoir d'agir, alors rien ne se produira jamais. On se trouve devant une chaîne de transmission sans rien à transmettre. Il faut donc nécessairement une cause première qui possède en elle-même, de manière non dérivée, l'efficacité causale. Cette cause première, Thomas l'identifie à Dieu, l'être dont l'essence implique l'existence (lipsum esse subsistens''), et qui confère l'être à toutes les créatures<ref>Mouracade, J.-M. (2013). « Causalité et hiérarchie ontologique chez Thomas d'Aquin », ''Revue thomiste'', vol. 113, p. 421-456</ref>. La causalité divine, selon Thomas, ne se limite pas à un acte de création initial situé au commencement du temps. Elle constitue une causalité conservatrice permanente : à chaque instant, Dieu maintient ses créatures dans l'être. Si cette action causale divine cessait ne serait-ce qu'un moment, les créatures retomberaient immédiatement dans le néant dont elles ont été tirées. La nécessité causale revêt ici une dimension métaphysique : l'existence même des choses contingentes dépend nécessairement, à chaque instant, de la causalité divine qui les maintient dans l'être. ====Leibniz et le principe de raison suffisante==== Au dix-septième siècle, Gottfried Wilhelm Leibniz systématise la conception de la causalité nécessaire en formulant explicitement le principe de raison suffisante. Ce principe, qu'il considère comme l'un des deux piliers de toute connaissance rationnelle (l'autre étant le principe de contradiction), énonce que rien n'existe et rien n'arrive sans qu'il y ait une raison suffisante pour laquelle c'est ainsi et non autrement<ref>Leibniz, G. W., ''Monadologie'', §32</ref>. Dans la ''Théodicée'', Leibniz formule cette exigence de manière lapidaire : « Rien n'arrive sans cause », et pour toute vérité, « on peut rendre raison »<ref>Leibniz, G. W., ''Théodicée'', §44</ref>. Le principe de raison suffisante ne se contente pas d'affirmer que tout a une cause, il précise la nature de cette causalité. Une raison suffisante n'est pas seulement une cause nécessaire (une condition sans laquelle l'effet ne se produirait pas), mais un ensemble complet de conditions qui, une fois posées, rendent l'effet inévitable. Leibniz emploie le terme de « réquisit » pour désigner ces conditions nécessaires : un réquisit est ce sans quoi une chose ne peut exister. Lorsque tous les réquisits d'une chose sont réunis, ils forment ensemble sa raison suffisante, et la chose existe nécessairement<ref>Melamed, Y. & Lin, M. (2016). « Principe de raison suffisante », dans ''Stanford Encyclopedia of Philosophy''</ref>. Cette conception de la raison suffisante s'articule étroitement avec la théorie leibnizienne de la vérité. Pour Leibniz, toute proposition vraie est analytique : le prédicat est contenu dans le sujet. Dans les vérités nécessaires (comme les vérités mathématiques), cette inclusion peut être démontrée en un nombre fini d'étapes par l'analyse des concepts. Dans les vérités contingentes (les vérités de fait concernant le monde existant), l'analyse se poursuit à l'infini, mais Dieu, dans son entendement infini, voit d'un seul regard l'inclusion du prédicat dans le sujet. Cette théorie implique que toutes les propriétés et tous les états d'une substance sont contenus dans son concept complet. Le concept individuel de Jules César contient ''a priori'' tous les prédicats qui lui seront véritablement attribués, y compris « franchir le Rubicon »<ref>Leibniz, G. W., ''Discours de métaphysique'', §13</ref>. Il s'ensuit que tout ce qui arrive à une substance découle nécessairement de sa nature ou essence. La causalité apparente entre substances distinctes se réduit en réalité à un développement nécessaire des concepts individuels, coordonné par l'harmonie préétablie que Dieu a instaurée entre toutes les substances. Lorsque je veux lever mon bras et que mon bras se lève, il n'y a pas de causalité transitive entre mon âme et mon corps ; plutôt, Dieu a préétabli une harmonie telle que les états de mon âme et les mouvements de mon corps se correspondent parfaitement, chacun se déployant selon sa propre loi interne<ref>Leibniz, G. W., ''Système nouveau de la nature et de la communication des substances'', §14</ref>. Cette doctrine conduit Leibniz au bord d'un nécessitarisme absolu : si tout ce qui arrive possède une raison suffisante qui le rend inévitable, comment préserver la contingence du monde et la liberté divine dans le choix de créer tel monde plutôt que tel autre ? Leibniz tente de résoudre cette difficulté en distinguant la nécessité métaphysique (ou logique) de la nécessité morale (ou hypothétique). Une vérité est métaphysiquement nécessaire si son contraire implique contradiction ; elle est moralement nécessaire si, bien que son contraire ne soit pas contradictoire, elle découle des perfections de Dieu qui choisit toujours le meilleur. Le monde existant est contingent au sens métaphysique (Dieu aurait pu créer d'autres mondes sans contradiction), mais nécessaire au sens moral (Dieu, étant parfait, devait nécessairement choisir le meilleur des mondes possibles). Cette subtile distinction a été jugée peu convaincante par nombre de critiques, qui y voient une distinction verbale masquant mal un déterminisme complet<ref>Parmentier, M. (1994). « Leibniz et le nécessitarisme », ''Revue de métaphysique et de morale'', vol. 99, n° 4, p. 453-479</ref>. ====Spinoza et la nécessité absolue de la nature==== C'est Baruch Spinoza qui tire les conclusions les plus intransigeantes de la conception de la causalité comme production nécessaire. Dans l'''Éthique démontrée selon l'ordre géométrique'', il construit un système philosophique où la nécessité causale règne sans exception ni restriction. Dès l'axiome 3 de la première partie, Spinoza pose : « D'une cause déterminée donnée suit nécessairement un effet ; et inversement, s'il n'y a nulle cause déterminée, il est impossible qu'un effet suive »<ref>Spinoza, B., ''Éthique'', I, axiome 3</ref>. Cette formulation épurée exprime l'essence même de la causalité spinoziste : le lien entre cause et effet constitue une nécessité absolue, non une simple régularité empirique. Pour Spinoza, comprendre quelque chose, c'est en saisir la cause. L'axiome 4 de la première partie affirme : « La connaissance de l'effet dépend de la connaissance de la cause et l'enveloppe »<ref>Spinoza, B., ''Éthique'', I, axiome 4</ref>. Cette formule ne signifie pas seulement que nous devons connaître la cause pour connaître l'effet (dimension épistémologique), mais que l'effet est réellement contenu dans la cause et en découle nécessairement (dimension ontologique). La relation causale s'apparente ainsi à une relation d'inhérence logique : l'effet est dans la cause comme la conclusion est dans les prémisses d'un raisonnement déductif. Spinoza identifie explicitement causalité et rationalité dans la formule ''causa sive ratio'' – la cause ou raison<ref>Spinoza, B., ''Éthique'', I, proposition 11, démonstration</ref>. Expliquer causalement un phénomène et en rendre raison constituent une seule et même opération intellectuelle. Cette identification repose sur une conception génétique de la définition : une définition vraie doit être génétique, c'est-à-dire qu'elle doit exprimer la cause productrice de la chose définie. Par exemple, la définition du cercle comme « la figure décrite par une ligne dont une extrémité est fixe et l'autre mobile » constitue une définition génétique qui montre comment le cercle peut être engendré. De cette définition, on peut déduire toutes les propriétés essentielles du cercle. La connaissance véritable procède ainsi par déduction causale : on part de la définition génétique (la cause) et on en déduit les propriétés (les effets). Le système spinoziste repose sur la démonstration qu'il existe une seule substance, Dieu ou la Nature (''Deus sive Natura''), qui existe nécessairement et dont tout le reste découle nécessairement. La proposition 16 de la première partie affirme : « De la nécessité de la nature divine doivent suivre une infinité de choses en une infinité de modes (c'est-à-dire tout ce qui peut tomber sous un entendement infini) »<ref>Spinoza, B., ''Éthique'', I, proposition 16</ref>. La démonstration recourt à une analogie mathématique : de même que l'entendement infère d'une définition donnée un nombre indéfini de propriétés qui suivent nécessairement de l'essence de la chose définie, de même de la nature divine, qui possède une infinité d'attributs exprimant chacun une essence infinie, doivent suivre nécessairement une infinité de choses en une infinité de modes. Cette proposition établit que tout ce qui existe découle nécessairement de la nature de Dieu. Spinoza en tire la conséquence que « dans la Nature, il n'y a rien de contingent, mais tout est déterminé par la nécessité de la nature divine à exister et à opérer d'une certaine façon » (proposition 29)<ref>Spinoza, B., ''Éthique'', I, proposition 29</ref>. Le contingent, entendu comme ce qui pourrait ne pas être, n'existe donc pas dans la réalité. Ce que nous appelons contingent n'est tel que relativement à notre ignorance des causes : si nous connaissions parfaitement la chaîne causale complète qui produit un événement, nous verrions qu'il ne pouvait pas ne pas se produire. La contingence est un défaut de connaissance, non une propriété ontologique. Ce nécessitarisme absolu soulève évidemment la question de la liberté divine. Si tout suit nécessairement de la nature de Dieu, Dieu lui-même est-il libre ? Spinoza répond en redéfinissant la liberté. Est libre, selon lui, « ce qui existe par la seule nécessité de sa nature et se détermine soi-même à agir »<ref>Spinoza, B., ''Éthique'', I, définition 7</ref>. Dieu est libre en ce sens suprême : il n'est contraint par aucune cause extérieure (puisqu'il est la seule substance), et il agit selon la nécessité de sa propre nature. Cette liberté s'oppose à la nécessité de contrainte (être forcé par une cause externe), non à la nécessité tout court. Spinoza critique vigoureusement la conception vulgaire de la liberté divine comme libre arbitre, comme si Dieu pouvait choisir de créer ou non, de créer tel monde plutôt que tel autre. Une telle conception anthropomorphique projette sur Dieu les imperfections de la volonté humaine. La causalité spinoziste présente une autre caractéristique essentielle : elle est immanente, non transitive. Dieu n'est pas une cause extérieure qui produirait le monde comme l'artisan produit un objet distinct de lui. Il est cause immanente : les choses finies (les modes) sont des manières d'être de la substance divine elle-même<ref>Spinoza, B., ''Éthique'', I, proposition 18</ref>. Cette conception s'oppose au théisme créationniste traditionnel, qui conçoit Dieu comme transcendant et le monde comme une réalité distincte, créée ''ex nihilo'' par un acte de volonté divine libre. Pour Spinoza, au contraire, Dieu et la Nature ne font qu'un, et le monde découle éternellement de la nature divine avec la même nécessité que les propriétés du triangle découlent de sa définition. L'essentialisme causal de Spinoza implique que chaque chose possède une essence qui détermine ses pouvoirs causaux. Les effets « suivent » de l'essence des choses comme les propriétés géométriques suivent des définitions. Cette approche fait de la causalité non pas une relation contingente entre événements séparés, mais l'expression nécessaire de la nature des choses<ref>Viljanen, V. (2008). « Spinoza's Essentialist Model of Causation », ''Inquiry'', vol. 51, n° 4, p. 412-437</ref>. La connaissance adéquate consiste précisément à saisir ces connexions causales nécessaires, à comprendre comment les modes finis s'enchaînent les uns aux autres selon des lois déterminées qui découlent de la nature divine. ====Enjeux et limites de la conception nécessitariste==== La conception de la causalité comme production nécessaire, qui culmine dans le système spinoziste, repose sur plusieurs présupposés qu'il convient d'examiner. Premier présupposé : l'intelligibilité du réel exige que tout ait une raison d'être. Sans le principe de raison suffisante, le monde serait un chaos incompréhensible où les choses arriveraient sans cause, arbitrairement. Ce présupposé exprime un optimisme rationaliste : le réel est rationnel, et la raison peut en principe rendre compte de tout ce qui existe. Deuxième présupposé : la causalité ne se réduit pas à une succession régulière d'événements, mais implique une connexion nécessaire, un lien ontologique qui fait que l'effet ne peut pas ne pas suivre de la cause. Ce présupposé distingue la métaphysique rationaliste de l'empirisme humien qui réduira la causalité à la régularité. Ces présupposés comportent des implications considérables. Si tout est déterminé par des causes nécessaires, quelle place reste-t-il pour la liberté humaine ? Spinoza affronte cette difficulté en niant le libre arbitre : les hommes se croient libres parce qu'ils sont conscients de leurs désirs et de leurs actions, mais ignorants des causes qui les déterminent. La véritable liberté ne consiste pas dans un pouvoir de choisir indifféremment entre des contraires (ce qui est une illusion), mais dans la compréhension adéquate de la nécessité qui nous détermine. En comprenant les causes qui nous font agir, nous cessons d'être passivement ballottés par des affects dont nous ignorons l'origine, et nous devenons actifs dans la mesure où nos actions découlent de notre propre nature comprise adéquatement<ref>Spinoza, B., ''Éthique'', III, proposition 2, scolie ; IV, proposition 66-73</ref>. Cette solution soulève toutefois des difficultés. Si tout est nécessaire, les notions morales de responsabilité, de mérite et de faute semblent perdre leur sens. Comment blâmer quelqu'un pour une action qu'il ne pouvait pas ne pas accomplir ? Spinoza répond que le blâme et la louange conservent une efficacité causale : ils constituent eux-mêmes des causes qui influencent le comportement futur, non pas en vertu d'une liberté métaphysique inexistante, mais en modifiant les affects et les représentations qui déterminent causalement les actions. La morale spinoziste ne repose pas sur l'imputation de fautes à une volonté libre, mais sur la compréhension des passions humaines et la recherche rationnelle de ce qui est véritablement utile à la conservation et au perfectionnement de notre être. D'un point de vue matérialiste contemporain, il convient de distinguer plusieurs sens de la nécessité causale. La nécessité logique (ce dont le contraire implique contradiction) ne se confond pas avec la nécessité nomologique (ce qui découle des lois de la nature). Les lois de la nature, loin d'être des vérités éternelles et immuables comme les vérités mathématiques, constituent des régularités qui ont elles-mêmes une histoire et peuvent évoluer. L'erreur des rationalistes du dix-septième siècle consiste à avoir confondu ces deux types de nécessité, modelant leur conception de la causalité naturelle sur le paradigme de la déduction mathématique. Une conception matérialiste et dialectique de la causalité reconnaît que les structures causales du monde ont une épaisseur historique : elles se sont constituées, elles évoluent, et l'action humaine collective peut les transformer. ===La pluralité des causes : Aristote et les quatre causes=== Avant même de s'interroger sur la nécessité du lien causal, Aristote pose une question plus fondamentale qui transforme la compréhension même de ce que signifie expliquer par les causes. Pour lui, chercher la cause d'un phénomène, c'est chercher le « pourquoi » (''to dia ti'' en grec), et cette recherche du pourquoi ne se satisfait pas d'une réponse unique. L'explication causale complète d'une chose exige de répondre à quatre questions distinctes, correspondant à quatre modes différents de causalité. Cette doctrine des quatre causes, exposée principalement dans la ''Physique'' (livre II, chapitres 3 à 9) et la ''Métaphysique'' (livre Delta, chapitre 2), constitue l'un des apports les plus durables d'Aristote à la philosophie<ref>Aristote, ''Physique'', II, 3, 194b16-195b30 ; ''Métaphysique'', Δ, 2, 1013a24-1013b28</ref>. ====Le cadre conceptuel : causalité et explication==== Pour comprendre la doctrine aristotélicienne, il faut d'abord saisir que le terme grec ''aitia'', que nous traduisons par « cause », possède un sens plus large que notre notion moderne. ''Aitia'' désigne à l'origine une responsabilité, une accusation, une culpabilité. Aristote en fait un terme technique de la philosophie pour désigner ce qui est responsable de quelque chose, ce dont dépend l'existence ou le devenir d'une chose<ref>Natali, C. (2013). « AITIA in Plato and Aristotle. From Everyday Language to Technical Vocabulary », ''Méthexis'', vol. 26, p. 3-25</ref>. L'innovation aristotélicienne consiste à reconnaître que cette dépendance peut s'exercer de plusieurs manières différentes, irréductibles les unes aux autres. Dans la ''Physique'', Aristote affirme explicitement : « Nous ne pensons pas connaître chaque chose avant que nous n'ayons d'abord saisi le pourquoi de chacune, c'est-à-dire sa cause »<ref>Aristote, ''Physique'', II, 3, 194b17-19</ref>. La connaissance scientifique (''epistémè'') ne se contente pas de constater qu'un phénomène se produit ; elle exige de comprendre pourquoi il se produit, quelle est sa raison d'être. Cette exigence explicative conduit Aristote à identifier quatre types de réponses à la question « pourquoi ? », correspondant à quatre types de causes. ====La cause matérielle : ce dont une chose est faite==== La cause matérielle (''hylè aitia'') désigne la matière dont une chose est constituée, le substrat à partir duquel elle est formée. Aristote la définit comme « ce de quoi une chose est faite en tant que constituant immanent »<ref>Aristote, ''Métaphysique'', Δ, 2, 1013a24-25</ref>. L'exemple classique est celui de la statue : l'airain ou le marbre constitue la cause matérielle de la statue. De même, les lettres sont la cause matérielle de la syllabe, et le bois est la cause matérielle de la table. Toutefois, il faut prendre garde à ne pas comprendre la cause matérielle de manière trop restrictive. La matière n'est pas nécessairement un substrat physique tangible. Dans certains cas, elle peut être de nature plus abstraite. Aristote précise que A et B sont la cause matérielle de la syllabe BA : les éléments dont quelque chose est composé en forment la cause matérielle, même si ces éléments ne sont pas à proprement parler des objets matériels au sens physique<ref>Aristote, ''Physique'', II, 3, 195a16-17</ref>. La cause matérielle répond donc à la question : de quoi est faite cette chose ? Quelle est sa composition ? Cette cause explique certaines propriétés de la chose : la lourdeur de la statue s'explique par sa matière de bronze, sa durabilité par la solidité du marbre. Mais la cause matérielle seule ne suffit pas à expliquer pleinement la chose. Savoir qu'une maison est faite de briques et de bois ne nous dit pas encore ce qu'est une maison, ni pourquoi ces matériaux ont été assemblés de cette manière particulière. Il faut donc recourir aux autres causes. ====La cause formelle : l'essence et la définition==== La cause formelle (''eidos aitia'' ou ''morphè aitia'') désigne la forme, la structure ou l'essence qui fait qu'une chose est ce qu'elle est. Aristote la définit comme « la forme et le modèle, c'est-à-dire la définition de l'essence »<ref>Aristote, ''Métaphysique'', Δ, 2, 1013a26-27</ref>. La cause formelle répond à la question : qu'est-ce que cette chose ? Quelle est sa nature essentielle ? Pour comprendre cette notion, prenons l'exemple de la statue. La cause formelle de telle statue n'est pas le marbre dont elle est faite (cause matérielle), mais la forme de David, c'est-à-dire cette configuration particulière qui fait que ce bloc de marbre sculpté représente David et non une autre figure. La forme est ce qui confère à la matière son intelligibilité : sans forme, la matière reste indéterminée, pure potentialité sans actualité définie. Dans la théorie aristotélicienne de l'hylémorphisme (du grec ''hylè'', matière, et ''morphè'', forme), toute substance matérielle est un composé de matière et de forme. La forme n'est pas une entité séparée existant dans un monde intelligible, comme chez Platon, mais un principe structurant immanent à la chose elle-même. Elle constitue son principe d'identité et d'intelligibilité. Connaître la cause formelle d'une chose, c'est pouvoir la définir, dire ce qu'elle est essentiellement. Aristote souligne que la cause formelle joue un rôle explicatif fondamental. Dans la ''Métaphysique'', il écrit que « la forme est l'essence, et l'essence est la cause première de l'être »<ref>Aristote, ''Métaphysique'', Z, 7, 1032b1-2</ref>. Ce qui fait qu'une chose est telle chose déterminée, ce n'est pas seulement sa matière (qui pourrait recevoir d'autres formes), mais sa forme qui actualise la matière de manière spécifique. Dans le cas des êtres vivants, la forme est l'âme (''psychè''), principe vital qui organise la matière corporelle et lui confère ses fonctions caractéristiques<ref>Aristote, ''De l'âme'', II, 1, 412a19-28</ref>. ====La cause efficiente : le principe du mouvement==== La cause efficiente ou cause motrice (''to kinoun'' ou ''to poioun'') désigne ce qui produit le changement, l'agent qui fait passer une chose de la puissance à l'acte. Aristote la définit comme « le principe premier du changement ou du repos »<ref>Aristote, ''Métaphysique'', Δ, 2, 1013a29-30</ref>. Cette cause répond à la question : d'où vient le changement ? Qui ou quoi a produit cette chose ? Les exemples qu'Aristote propose sont parlants : le père est la cause efficiente de l'enfant, le sculpteur est la cause efficiente de la statue, celui qui délibère est la cause efficiente de son action<ref>Aristote, ''Physique'', II, 3, 194b29-32</ref>. Dans chaque cas, la cause efficiente est ce qui initie le processus, ce qui met en mouvement ou transforme. Sans cause efficiente, rien ne passerait de la puissance à l'acte, la matière informée resterait à l'état de simple possibilité. La cause efficiente correspond assez étroitement à ce que la philosophie et la science modernes entendent par « cause ». C'est elle qui établit une relation de production temporelle : la cause efficiente précède temporellement son effet (le sculpteur commence à sculpter avant que la statue n'existe), et elle le produit par son action. Toutefois, Aristote précise que cause et effet peuvent aussi être simultanés dans certains cas : au moment où le médecin soigne, la guérison commence ; au moment où le bâtisseur construit, la maison s'édifie<ref>Aristote, ''Physique'', II, 3, 195b16-21</ref>. Il importe de noter qu'Aristote distingue la cause efficiente principale de la cause efficiente instrumentale. Le sculpteur est la cause principale, le ciseau est la cause instrumentale. La cause principale possède en elle-même le pouvoir d'agir, tandis que la cause instrumentale n'agit qu'en étant mue par la cause principale. Cette distinction sera reprise et développée par la scolastique médiévale dans la théorie de la causalité divine et des causes secondes. ====La cause finale : le but et la téléologie==== La cause finale (''to telos'' ou ''to hou heneka'') désigne le but, la fin en vue de laquelle quelque chose existe ou se produit. Aristote la définit comme « ce en vue de quoi une chose est »<ref>Aristote, ''Métaphysique'', Δ, 2, 1013a32-33</ref>. La cause finale répond à la question : dans quel but ? Pour quelle fin ? L'exemple aristotélicien classique est celui de la promenade : la santé est la cause finale de la promenade. On ne se promène pas sans raison ; on se promène en vue d'un bien, en l'occurrence la santé. De même, la cause finale d'une maison est d'abriter ses habitants ; la cause finale d'une statue peut être de commémorer un personnage illustre. Dans les productions artisanales et les actions humaines, la cause finale coïncide souvent avec l'intention ou le projet de l'agent. Mais Aristote étend la causalité finale bien au-delà des productions humaines intentionnelles. Il affirme que la nature elle-même agit en vue d'une fin : « La nature ne fait rien en vain, mais toujours en vue du meilleur parmi les possibles »<ref>Aristote, ''Marche des animaux'', 2, 704b15-17</ref>. Les processus naturels, notamment dans les êtres vivants, manifestent une finalité immanente. L'arbre pousse en vue de sa forme adulte, l'œil existe en vue de la vision, les organes se développent en vue de leurs fonctions caractéristiques. Cette téléologie naturelle ne suppose pas une conscience ou une intention dans la nature, mais simplement que les processus naturels sont orientés vers des fins déterminées qui correspondent au bien ou à la perfection de chaque être<ref>Aristote, ''Physique'', II, 8, 198b10-199b33</ref>. La cause finale occupe une place privilégiée dans la doctrine aristotélicienne. Aristote affirme qu'elle est « la cause des causes » (''aitia tôn aitiôn'') en ce sens que c'est elle qui rend compte de toutes les autres. Pourquoi telle matière a-t-elle été choisie ? Pourquoi telle forme a-t-elle été réalisée ? Pourquoi tel agent a-t-il agi ? La réponse ultime fait appel à la fin : en vue de tel but. La cause finale confère son intelligibilité complète au processus causal : elle explique non seulement que quelque chose s'est produit, mais pourquoi il devait se produire ainsi plutôt qu'autrement<ref>Falcon, A. (2019). ''Aristotle on Causality'', dans ''Stanford Encyclopedia of Philosophy''</ref>. ====L'interdépendance des quatre causes==== Un point essentiel de la doctrine aristotélicienne est que les quatre causes ne sont pas indépendantes les unes des autres ; elles collaborent à l'explication complète d'un même phénomène. Aristote insiste sur le fait qu'une explication adéquate requiert souvent de mobiliser plusieurs causes simultanément, voire les quatre. Prenons l'exemple de la statue de bronze représentant un discobole. La cause matérielle est le bronze ; la cause formelle est la configuration qui représente un athlète lançant le disque ; la cause efficiente est le sculpteur qui a façonné le bronze ; la cause finale peut être de célébrer la beauté athlétique ou de commémorer une victoire olympique. Ces quatre causes ne s'excluent pas mutuellement ; elles offrent quatre perspectives complémentaires sur la même réalité. Chacune répond à une question différente sur la statue, et c'est seulement en les combinant que nous obtenons une compréhension complète. Aristote note également que dans certains cas, plusieurs causes peuvent coïncider. La forme et la fin tendent souvent à se confondre : la forme adulte de l'arbre est à la fois la cause formelle (ce qu'est l'arbre dans sa maturité) et la cause finale (ce vers quoi tend sa croissance). De même, la cause efficiente et la cause formelle peuvent coïncider lorsqu'un artisan réalise une œuvre : la forme de la maison existe d'abord dans l'esprit de l'architecte (cause formelle) qui est aussi celui qui dirige la construction (cause efficiente)<ref>Aristote, ''Métaphysique'', Δ, 2, 1013b5-9</ref>. Cette interdépendance manifeste la complexité de la réalité naturelle et artificielle. Les choses ne se réduisent pas à une seule dimension causale ; elles requièrent une approche multidimensionnelle qui prenne en compte leur composition matérielle, leur structure formelle, leur origine productive et leur orientation téléologique. C'est cette vision holistique de la causalité qui distingue Aristote des penseurs présocratiques qui tendaient à privilégier un seul type d'explication (généralement matérielle). ====La postérité et les transformations de la doctrine==== La théorie aristotélicienne des quatre causes exercera une influence considérable sur toute la tradition philosophique occidentale. La scolastique médiévale, en particulier chez Thomas d'Aquin, reprend intégralement cette classification en l'adaptant au cadre de la théologie chrétienne. Thomas distingue entre causes intrinsèques (matérielle et formelle, qui sont des principes constitutifs de la chose) et causes extrinsèques (efficiente et finale, qui agissent de l'extérieur), et il établit une hiérarchie entre elles : la cause finale est la plus importante, suivie de la cause efficiente, puis de la cause formelle et enfin de la cause matérielle<ref>Thomas d'Aquin, ''Somme théologique'', I-II, q. 1, a. 2</ref><ref>Reece, B. C. (2019). « Aristotle's Four Causes of Action », ''Australasian Journal of Philosophy'', vol. 97, n° 2, p. 213-227</ref>. Thomas intègre également Dieu dans ce schéma causal : Dieu est la cause efficiente première de toute chose (en tant que créateur), la cause finale ultime (en tant que bien suprême vers lequel tout tend), et dans un certain sens la cause formelle exemplaire (en tant que modèle archétypal de toute perfection). Cette intégration de la causalité divine avec la causalité naturelle aboutit à la doctrine complexe de la coopération entre cause première (Dieu) et causes secondes (les créatures)<ref>Silva, I. (2015). « A Cause Among Causes ? God Acting in the Natural Order », ''American Catholic Philosophical Quarterly'', vol. 89, n° 4, p. 565-589</ref>. Cependant, la modernité scientifique, à partir du dix-septième siècle, opère une rupture avec cette conception quadripartite. La révolution scientifique moderne privilégie la cause efficiente comme seul type de causalité véritablement scientifique. Francis Bacon, René Descartes et leurs successeurs rejettent la cause finale comme anthropomorphique et invérifiable. La nature, selon eux, n'agit pas en vue de fins, mais selon des lois mécaniques qui relient des causes efficientes à leurs effets. La cause formelle est progressivement abandonnée ou réduite à la structure mathématique des lois naturelles. Quant à la cause matérielle, elle est intégrée dans une conception mécaniste où la matière possède des propriétés quantifiables (masse, étendue, mouvement) qui suffisent à rendre compte des phénomènes. Cette réduction de la causalité à la seule causalité efficiente mécaniste domine la pensée scientifique moderne. Toutefois, certains domaines, notamment la biologie et les sciences humaines, continuent d'utiliser des explications fonctionnelles ou téléologiques qui s'apparentent aux causes finales aristotéliciennes, bien que sous une forme sécularisée et naturaliste. La question de savoir si l'on peut se passer entièrement de la téléologie dans l'explication des phénomènes vivants et des actions humaines reste débattue<ref>Charles, D. (2012). « Teleological Causation », dans C. Shields (éd.), ''The Oxford Handbook of Aristotle'', Oxford, Oxford University Press, p. 227-266</ref>. ====Enjeux philosophiques et critiques contemporaines==== D'un point de vue critique, plusieurs objections peuvent être adressées à la théorie aristotélicienne. Premièrement, la distinction entre les quatre causes n'est peut-être pas aussi nette qu'Aristote le suppose. Dans certains cas, il est difficile de séparer clairement la cause formelle de la cause finale, ou la cause efficiente de la cause matérielle. Cette porosité des frontières entre les types de causes suggère que la classification quadripartite pourrait être en partie artificielle. Deuxièmement, la généralisation de la causalité finale à toute la nature pose problème. Attribuer des fins aux processus naturels inanimés paraît anthropomorphique. Si l'on peut admettre que les êtres vivants manifestent une sorte de finalité (même si celle-ci peut être expliquée en termes évolutionnistes sans recourir à un dessein intelligent), il est plus difficile de voir en quoi un caillou qui tombe ou un fleuve qui coule agiraient « en vue d'une fin ». La science moderne a montré qu'on peut expliquer les phénomènes naturels sans invoquer de finalité, simplement par des lois causales efficientes. Troisièmement, la théorie aristotélicienne ne problématise pas suffisamment le lien entre cause et effet. Elle prend pour acquis que les causes produisent nécessairement leurs effets, sans examiner la nature de cette nécessité. C'est cette lacune que la critique humienne mettra en lumière : qu'est-ce qui garantit que de la même cause suivra toujours le même effet ? La réponse aristotélicienne – parce que telle est la nature de la chose – ne satisfait plus une pensée empiriste qui exige de fonder la connaissance sur l'observation. Malgré ces limites, la doctrine aristotélicienne des quatre causes conserve une valeur philosophique. Elle rappelle que l'explication causale ne se réduit pas à un seul modèle, mais peut prendre des formes multiples selon le type de question que l'on pose et le domaine de réalité que l'on étudie. Elle invite à une approche pluraliste de la causalité, reconnaissant que différents types d'explications peuvent coexister sans nécessairement se contredire. Cette leçon reste pertinente pour la philosophie contemporaine des sciences, qui s'interroge sur la diversité des modèles explicatifs utilisés dans différentes disciplines<ref>Stein, N. (2012). « Causality and Causal Explanation in Aristotle », ''Philosophy Compass'', vol. 7, n° 10, p. 699-711</ref>. ==La critique humienne et le problème de la connexion nécessaire== ===Hume et la déconstruction de la nécessité causale=== David Hume opère une rupture fondamentale dans la pensée de la causalité en soumettant cette notion à une critique empiriste radicale. Son analyse part d'une question apparemment simple : d'où vient notre idée de causalité, et que pouvons-nous légitimement affirmer sur les relations causales ? La réponse de Hume est dévastatrice pour la conception traditionnelle : nous ne pouvons jamais observer directement une connexion nécessaire entre une cause et son effet<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', section VII</ref>. Lorsque nous observons un événement A suivi d'un événement B, que percevons-nous exactement ? Nous observons trois choses : la contiguïté spatiale (A et B sont proches dans l'espace), la succession temporelle (A précède B dans le temps), et, si nous répétons l'observation, la conjonction constante (chaque fois que A se produit, B suit). Mais nous ne percevons jamais la prétendue « connexion nécessaire » qui ferait que A ''doit'' produire B. Cette connexion nécessaire n'est pas une impression sensible ; elle ne peut donc pas fonder une connaissance légitime selon les critères empiristes de Hume. D'où vient alors notre conviction que les causes produisent nécessairement leurs effets ? Hume répond : de l'habitude. Après avoir observé la conjonction répétée de A et B, notre esprit s'habitue à cette séquence et développe une attente psychologique : lorsque A se produit, nous nous attendons à ce que B suive. Cette attente n'est pas le résultat d'un raisonnement, mais d'un mécanisme psychologique, d'une « coutume »<ref>Hume, D. (1739-1740). ''Traité de la nature humaine'', I, III, §14</ref>. La nécessité causale n'est donc pas dans les choses, mais dans notre esprit : elle est subjective et non objective. Hume propose ainsi une double définition de la cause. D'un point de vue objectif, « nous pouvons définir une cause comme un objet suivi d'un autre, et où tous les objets semblables au premier sont suivis d'objets semblables au second ». D'un point de vue subjectif, une cause est « un objet suivi d'un autre, et dont l'apparition conduit toujours la pensée à cet autre »<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', section VII, partie 2</ref>. La première définition réduit la causalité à la régularité ; la seconde la psychologise en en faisant une habitude mentale. ===Le problème de l'induction et le scepticisme causal=== La critique humienne de la causalité conduit directement au célèbre problème de l'induction. Si la causalité n'est que conjonction constante, comment justifier que nous inférions du passé au futur ? Autrement dit, pourquoi le fait que A ait toujours été suivi de B par le passé nous autorise-t-il à croire que A sera suivi de B dans le futur ? Hume montre qu'une telle inférence suppose un principe qu'il appelle le « principe d'uniformité de la nature » : la nature continue de fonctionner de la même manière, les mêmes causes produiront les mêmes effets. Mais ce principe lui-même ne peut être justifié ni par la raison (car sa négation n'est pas contradictoire), ni par l'expérience (car invoquer l'expérience passée pour justifier les inférences futures serait circulaire)<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', section IV, partie 2</ref>. Le résultat est un scepticisme causal profond : nous n'avons aucune justification rationnelle pour nos croyances causales les plus ordinaires. Nous croyons que le soleil se lèvera demain, que le pain nous nourrira, que le feu brûlera, mais ces croyances reposent uniquement sur l'habitude, non sur la raison. Ce scepticisme ne conduit pas Hume à renoncer à nos croyances causales dans la pratique (ce serait impossible), mais il révèle leurs limites épistémologiques<ref>Dimech, D. K. (2019). « Quasi-Realism and Inductive Scepticism in Hume's Theory of Causation », ''Australasian Journal of Philosophy'', 97(1), p. 143-157</ref>. Cette analyse humienne a eu des conséquences majeures. D'une part, elle a inspiré les théories régularistes de la causalité qui rejettent toute notion de connexion nécessaire. D'autre part, elle a posé un défi que la philosophie ultérieure n'a cessé de tenter de relever : comment fonder rationnellement nos inférences causales ? ==La réponse kantienne : la causalité comme catégorie de l'entendement== ===La causalité comme condition a priori de l'expérience=== Face au scepticisme humien, Kant propose une solution originale qui transforme radicalement le statut de la causalité. Loin de chercher à dériver l'idée de causalité de l'expérience (comme le font les empiristes) ou de la traiter comme une propriété objective des choses en soi, Kant fait de la causalité une catégorie a priori de l'entendement, c'est-à-dire une structure conceptuelle que l'esprit impose nécessairement à l'expérience pour la rendre intelligible<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', Analytique transcendantale, Analogies de l'expérience</ref>. Pour Kant, Hume a raison sur un point : nous ne pouvons pas tirer le concept de causalité de l'expérience par simple généralisation. Mais il a tort d'en conclure que la causalité n'est qu'une habitude subjective. En réalité, la causalité est une condition de possibilité de l'expérience objective elle-même. Sans le concept de cause, nous ne pourrions pas distinguer une succession objective d'événements (où A cause réellement B) d'une simple succession subjective de nos perceptions (où nous percevons d'abord A puis B, sans que l'un cause l'autre). L'argument de Kant, développé dans la « Deuxième Analogie de l'expérience », peut être résumé ainsi : pour qu'il y ait expérience objective (connaissance d'objets dans le temps), il faut que nous puissions déterminer un ordre temporel objectif des événements. Or, cet ordre ne peut être déterminé que si nous supposons que les événements sont liés par des relations causales nécessaires. Donc, le principe de causalité (« tout changement a une cause ») est une condition nécessaire de l'expérience objective<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', B232-256</ref>. Prenons l'exemple kantien célèbre du bateau qui descend le fleuve. Lorsque je perçois d'abord le bateau en amont puis en aval, cet ordre de mes perceptions est irréversible : je ne peux pas percevoir le bateau d'abord en aval puis en amont. Cette irréversibilité objective de la séquence perceptive indique que je perçois un événement objectif (le mouvement du bateau), et non une simple succession arbitraire de mes représentations. Mais pour distinguer cette succession objective d'une succession purement subjective, je dois supposer que le bateau est causalement déterminé à se déplacer d'amont en aval<ref>Kannisto, T. (2017). « Kant on the Necessity of Causal Relations », ''Kant-Studien'', 108(4), p. 645-668</ref>. ===Faiblesse et force du principe causal kantien=== Kant défend une version relativement faible du principe de causalité, ce que les commentateurs appellent le « principe causal faible » (Weak Causal Principle). Ce principe affirme que tout événement a ''une'' cause, mais ne précise pas que les mêmes types de causes produisent toujours les mêmes types d'effets. Autrement dit, Kant démontre dans la Deuxième Analogie que chaque événement particulier doit avoir une cause, mais pas qu'il existe des lois causales universelles reliant des types d'événements<ref>Kannisto, T. (2017). « Kant on the Necessity of Causal Relations », ''Kant-Studien'', 108(4), p. 645-668</ref>. La version forte du principe de causalité (Strong Causal Principle), qui affirme que les mêmes causes produisent toujours les mêmes effets, n'est selon certains interprètes démontrée par Kant que dans les « Postulats de la pensée empirique », où il traite de la nécessité modale. C'est seulement là que Kant établirait que les relations causales ne sont pas seulement nécessaires dans chaque cas particulier, mais obéissent à des lois constantes qui permettent la prédiction<ref>Kannisto, T. (2017). « Kant on the Necessity of Causal Relations », ''Kant-Studien'', 108(4), p. 645-668</ref>. Cette subtilité est importante : elle montre que même pour Kant, qui défend la nécessité de la causalité, il existe différents degrés de nécessité causale. La causalité comme condition de l'expérience objective n'implique pas automatiquement l'existence de lois causales strictement universelles et exceptionless. Un autre aspect essentiel de la théorie kantienne est que la causalité n'est pas une propriété des choses en soi, mais seulement des phénomènes, c'est-à-dire des choses telles qu'elles nous apparaissent dans l'expérience. Nous ne pouvons rien savoir de la causalité dans le monde nouménal. Cette limitation aura des conséquences importantes pour la philosophie ultérieure, notamment pour penser la liberté humaine dans un monde où règne le déterminisme causal phénoménal. ==L'occasionnalisme et la causalité divine== ===Le problème cartésien de l'interaction âme-corps=== La philosophie cartésienne, en instituant une séparation radicale entre deux substances hétérogènes – la substance pensante (''res cogitans'') et la substance étendue (''res extensa'') – crée un problème théorique majeur : comment ces deux substances peuvent-elles interagir causalement ? Comment ma volonté (immatérielle) peut-elle causer le mouvement de mon bras (matériel) ? Comment la piqûre d'une épine (matérielle) peut-elle causer ma douleur (immatérielle) ? Descartes lui-même propose une solution en introduisant la notion de « causes qui donnent occasion ». Dans certains textes, il suggère que la volonté ne cause pas ''directement'' le mouvement du corps, mais donne l'occasion à certains mécanismes physiologiques de se déclencher<ref>Descartes, R. (1649). ''Les Passions de l'âme'', art. 41</ref>. Cette formulation prudente a ouvert la voie à une interprétation plus radicale chez ses successeurs cartésiens. ===Malebranche et l'occasionnalisme systématique=== Nicolas Malebranche pousse la logique cartésienne jusqu'à ses conséquences ultimes en développant la doctrine de l'occasionnalisme. Selon cette théorie, les causes naturelles (qu'il s'agisse de l'interaction âme-corps ou de l'action d'un corps sur un autre) ne sont pas de véritables causes efficientes, mais seulement des causes occasionnelles qui donnent à Dieu l'occasion d'exercer sa causalité. Seul Dieu est la véritable cause efficiente de tout ce qui se produit dans le monde<ref>Malebranche, N. (1674-1675). ''De la recherche de la vérité'', livre VI, partie II, chapitre III</ref>. L'argument principal de Malebranche repose sur l'idée qu'une véritable cause doit avoir une connexion nécessaire avec son effet. Or, nous ne concevons aucune connexion nécessaire entre les prétendues causes naturelles et leurs effets. Nous ne voyons aucune liaison nécessaire entre ma volonté de lever le bras et le mouvement effectif de mon bras ; nous ne voyons aucune liaison nécessaire entre le choc d'une boule de billard contre une autre et le mouvement de la seconde. Seul Dieu, dont la volonté toute-puissante ne peut être empêchée, possède une véritable efficacité causale<ref>Malebranche, N. (1674-1675). ''De la recherche de la vérité'', Éclaircissement XV</ref>. Cette position a des conséquences théologiques et métaphysiques considérables. Elle fait de Dieu non pas seulement le créateur initial du monde, mais l'agent perpétuel de tout changement. Chaque mouvement, chaque pensée, chaque sensation est l'effet direct de la volonté divine. Les lois de la nature deviennent des lois que Dieu s'est données à lui-même, des régularités dans sa manière d'agir. L'occasionnalisme affirme ainsi une dépendance causale absolue de la création vis-à-vis du créateur. ===Critiques et héritage de l'occasionnalisme=== L'occasionnalisme a suscité de nombreuses objections. Leibniz critique cette doctrine en arguant qu'elle fait de Dieu un « Deus ex machina » qui intervient continuellement dans la nature, ce qui est indigne de sa perfection. Pour Leibniz, Dieu a créé le monde de telle sorte que les substances créées possèdent de véritables forces actives et peuvent agir par elles-mêmes, selon lharmonie préétablie''<ref>Leibniz, G. W. (1695). ''Système nouveau de la nature et de la communication des substances''</ref>. Fontenelle, dans ses ''Doutes sur le système physique des causes occasionnelles'', critique l'occasionnalisme d'un point de vue épistémologique en soulignant qu'il rend la science naturelle impossible : si Dieu est la seule cause véritable, pourquoi chercher les causes naturelles ? L'occasionnalisme, en supprimant l'efficacité causale de la nature, supprime aussi la possibilité d'une explication scientifique autonome<ref>Rioux-Beaulne, M. (2018). « Fontenelle, Malebranche et les limites de la causalité », ''Revue philosophique de la France et de l'étranger'', 143(3), p. 365-388</ref>. Paradoxalement, en niant toute causalité naturelle, l'occasionnalisme a préparé le terrain pour la critique humienne. En montrant qu'aucune connexion nécessaire n'est observable entre les événements naturels, Malebranche a sapé les fondements de la causalité efficiente. Hume n'aura plus qu'à faire un pas supplémentaire : retirer Dieu de l'équation et conclure qu'il n'existe tout simplement pas de connexion nécessaire du tout<ref>Le Ru, V. (2005). « La réception occasionaliste de Descartes », ''Recherches sur Diderot et sur l'Encyclopédie'', 38, p. 83-100</ref>. ==Les théories régularistes et la causalité comme loi== ===Mill et l'analyse des conditions multiples=== John Stuart Mill développe une analyse sophistiquée de la causalité qui prend acte de la critique humienne tout en cherchant à la dépasser. Pour Mill, Hume a raison de lier causalité et régularité, mais sa conception est trop simple. La causalité ne se réduit pas à la succession constante de deux événements isolés ; elle implique un ensemble complexe de conditions<ref>Mill, J. S. (1843). ''A System of Logic'', livre III, chapitre V</ref>. Mill introduit la distinction cruciale entre la cause totale d'un phénomène et les causes partielles qui la composent. La cause totale est l'ensemble complet des conditions positives et négatives qui, conjointement, sont suffisantes pour produire l'effet. Prenons l'exemple de l'incendie d'une maison : nous disons ordinairement que c'est l'allumette qui a causé l'incendie, mais en réalité, l'allumette n'est qu'une partie de la cause totale, qui inclut aussi la présence d'oxygène, l'inflammabilité du matériau, l'absence de système d'extinction automatique, etc. Cette analyse conduit Mill à définir la cause comme « l'antécédent invariable et inconditionnel d'un phénomène ». Par « invariable », il entend que la cause est toujours suivie de l'effet ; par « inconditionnel », qu'elle le produit quelles que soient les autres circonstances (une fois réalisées les autres conditions de la cause totale). Cette définition préserve l'idée humienne de régularité tout en la complexifiant pour tenir compte de la pluralité des facteurs causaux. Mill développe également des méthodes d'enquête expérimentale (les fameuses « méthodes de Mill ») pour découvrir les relations causales. La méthode de concordance consiste à rechercher ce qui est commun à tous les cas où l'effet se produit. La méthode de différence cherche ce qui distingue les cas où l'effet se produit des cas où il ne se produit pas. La méthode conjointe de concordance et de différence combine les deux approches. La méthode des variations concomitantes examine si les variations de l'effet suivent celles de la cause supposée. Enfin, la méthode des résidus consiste à soustraire les effets des causes connues pour isoler l'effet d'une cause encore inconnue<ref>Mill, J. S. (1843). ''A System of Logic'', livre III, chapitre VIII</ref>. ===Les conditions INUS et la complexité causale=== L'analyse millienne a été raffinée au XXe siècle par John Mackie avec sa théorie des conditions INUS. INUS est l'acronyme de « Insufficient but Necessary part of a condition which is Unnecessary but Sufficient » (partie insuffisante mais nécessaire d'une condition qui n'est pas nécessaire mais suffisante)<ref>Mackie, J. L. (1974). ''The Cement of the Universe'', Oxford : Clarendon Press</ref>. Prenons à nouveau l'exemple de l'incendie. L'allumette enflammée (A) n'est pas à elle seule suffisante pour causer l'incendie : elle doit être accompagnée d'autres conditions comme la présence d'oxygène (B), l'inflammabilité du matériau (C), etc. L'ensemble {A, B, C} forme une condition suffisante pour l'incendie. Mais cette condition n'est pas nécessaire car l'incendie pourrait aussi être causé par un court-circuit {D, E, F} ou par un incendie criminel {G, H, I}. Ainsi, A est une condition INUS : elle est insuffisante seule (elle a besoin de B et C), mais nécessaire au sein de l'ensemble {A, B, C} ; cet ensemble est suffisant pour l'incendie, mais pas nécessaire (car {D, E, F} serait également suffisant). Cette analyse montre la complexité réelle des situations causales : rarement une cause unique produit un effet, et rarement un effet ne peut être produit que d'une seule manière. La causalité est presque toujours plurielle (plusieurs facteurs concourent à l'effet) et contingente (l'effet pourrait être produit par d'autres combinaisons de facteurs). Cette vision contraste avec l'image simplifiée de la causalité comme relation binaire entre une cause et un effet. ==Les approches contrefactuelles de la causalité== ===Lewis et la dépendance contrefactuelle=== David Lewis propose au début des années 1970 une théorie influente qui renouvelle l'approche de la causalité en la fondant sur les contrefactuels (counterfactuals). L'idée de base est que nous pensons qu'un événement C a causé un événement E si et seulement si, dans la situation contrefactuelle où C ne se serait pas produit, E ne se serait pas produit non plus<ref>Lewis, D. (1973). « Causation », ''Journal of Philosophy'', 70(17), p. 556-567</ref>. Pour évaluer ces contrefactuels, Lewis utilise une sémantique des mondes possibles. Un contrefactuel « Si C n'avait pas eu lieu, E n'aurait pas eu lieu » est vrai dans le monde actuel si et seulement si, dans les mondes possibles les plus proches du monde actuel où C ne se produit pas, E ne se produit pas non plus. La « proximité » ou « similarité » entre mondes possibles se mesure selon plusieurs critères : concordance des lois naturelles, similitude des faits particuliers, absence de « miracles » (violations localisées des lois), etc.<ref>Lewis, D. (1979). « Counterfactual Dependence and Time's Arrow », ''Noûs'', 13(4), p. 455-476</ref>. Lewis distingue ensuite la dépendance causale de la causation elle-même. Deux événements distincts E et C présentent une dépendance causale si et seulement si : (1) si C s'était produit, E se serait produit ; et (2) si C ne s'était pas produit, E ne se serait pas produit. La causation est alors définie comme l'ancestrale de la dépendance causale : C cause E s'il existe une chaîne d'événements intermédiaires reliés par des relations de dépendance causale. Cette distinction entre dépendance causale et causation est nécessaire pour préserver la transitivité de la relation causale. Si C cause D, et D cause E, alors C cause E, même si E ne dépend pas causalement de C (parce qu'un autre facteur aurait pu produire D et, par suite, E, même en l'absence de C). ===Problèmes et raffinements : préemption et surdétermination=== La théorie de Lewis fait face à des contre-exemples célèbres, notamment les cas de préemption (preemption) et de surdétermination causale (overdetermination). Dans un cas de préemption, deux causes potentielles sont en concurrence, mais une seule aboutit effectivement : Suzy et Billy lancent chacun une pierre vers une bouteille ; la pierre de Suzy arrive en premier et brise la bouteille ; celle de Billy arrive une fraction de seconde plus tard et ne rencontre que des éclats de verre. Intuitivement, c'est le lancer de Suzy qui a causé le bris de la bouteille. Pourtant, le bris ne dépend pas causalement du lancer de Suzy au sens de Lewis, puisque si Suzy n'avait pas lancé sa pierre, Billy aurait brisé la bouteille<ref>Collins, J., Hall, N., & Paul, L. A. (2004). ''Causation and Counterfactuals'', Cambridge, MA : MIT Press</ref>. Face à ces difficultés, Lewis a proposé plusieurs révisions de sa théorie. Dans sa version tardive, il développe une théorie de l'influence causale (causal influence) fondée non plus sur la simple dépendance « si oui ou non » (whether-whether dependence), mais sur une dépendance plus fine portant sur la manière dont les événements se produisent (whether-when-how dependence). C'est la théorie de la « covariation contrefactuelle » : il y a influence causale de C sur E s'il existe une gamme de variations contrefactuelles de C qui correspondraient à des variations de E<ref>Lewis, D. (2000). « Causation as Influence », ''Journal of Philosophy'', 97(4), p. 182-197</ref>. Malgré ces raffinements, les théories contrefactuelles restent controversées. Certains philosophes estiment qu'elles présupposent ce qu'elles prétendent expliquer (puisque la notion de « monde possible proche » fait appel à des intuitions causales), d'autres qu'elles ne peuvent rendre compte de tous les jugements causaux ordinaires, notamment en cas d'absence causale (quand c'est l'absence d'un événement qui cause un effet). ==La causalité et la physique moderne== ===L'argument de Russell : la causalité exclue de la physique fondamentale=== En 1913, Bertrand Russell publie un article provocateur intitulé « On the Notion of Cause » dans lequel il soutient que la notion de cause n'a aucune place dans la physique moderne et devrait être abandonnée par la philosophie<ref>Russell, B. (1913). « On the Notion of Cause », ''Proceedings of the Aristotelian Society'', 13, p. 1-26</ref>. Selon Russell, la physique mathématisée ne fait appel qu'à des équations différentielles exprimant des relations fonctionnelles entre grandeurs, et non à des « causes » qui « produiraient » leurs « effets ». L'argument de Russell repose sur plusieurs observations. Premièrement, le mot « cause » n'apparaît jamais dans les équations fondamentales de la physique (comme F=ma). Deuxièmement, les lois physiques sont globales : elles mettent en relation l'état complet de l'univers (ou d'une grande région de l'espace-temps) à un instant avec son état à un autre instant, et non des événements locaux isolés comme le voudrait notre concept ordinaire de cause. Troisièmement, les lois physiques fondamentales sont symétriques dans le temps : elles permettent de prédire l'avenir à partir du présent, mais aussi de « rétrédire » le passé à partir du présent. Or, la causalité est asymétrique : les causes précèdent leurs effets, pas l'inverse<ref>Blanchard, T. (2016). « Physics and Causation », ''Philosophy Compass'', 11(5), p. 256-266</ref>. Russell conclut que la « loi de causalité », selon laquelle tout événement a une cause, est « une relique d'une ère révolue, survivant, comme la monarchie, seulement parce qu'on suppose à tort qu'elle ne fait pas de mal ». La physique moderne nous montre un univers de relations fonctionnelles mathématiques, non un univers de causes et d'effets. ===Réponses et controverses=== L'argument de Russell a suscité un débat qui continue aujourd'hui. Certains philosophes, comme John Norton, Huw Price ou Hartry Field, défendent une position néo-russellienne : la causalité n'appartient pas à l'ontologie fondamentale révélée par la physique, mais est au mieux un concept utile pour des descriptions de niveau supérieur ou une projection anthropomorphique<ref>Field, H. (2003). « Causation in a Physical World », in M. Loux & D. Zimmerman (eds.), ''The Oxford Handbook of Metaphysics'', Oxford : Oxford University Press</ref><ref>Norton, J. D. (2003). « Causation as Folk Science », ''Philosophers' Imprint'', 3(4), p. 1-22</ref>. D'autres philosophes résistent à cette conclusion. Ils font valoir que même si le vocabulaire causal n'apparaît pas explicitement dans les équations physiques, les physiciens utilisent constamment des notions causales dans leur pratique : ils parlent d'interactions causales, de propagation de signaux, d'effets d'une force, etc. De plus, certaines structures de la physique moderne peuvent être interprétées en termes causaux : par exemple, la relativité restreinte avec son cône de lumière établit des contraintes sur les relations causales possibles (seuls les événements dans le cône de lumière passé d'un événement peuvent l'influencer causalement)<ref>Frisch, M. (2020). « Causation in Physics », ''Stanford Encyclopedia of Philosophy''</ref>. Une position médiane consiste à distinguer différents niveaux d'analyse : la physique fondamentale décrirait des structures non causales (ou pré-causales), tandis que les sciences spéciales et le sens commun utiliseraient légitimement des concepts causaux pour décrire des régularités à des échelles supérieures. La causalité serait alors une notion émergente ou contextuelle, non fondamentale mais non moins réelle pour autant. ===Causalité et mécanique quantique=== La mécanique quantique soulève des questions spécifiques sur la causalité. Le principe d'indéterminisme quantique affirme que certains processus (comme la désintégration d'un atome radioactif) se produisent spontanément, sans cause déterminante. Cela remet en question le principe traditionnel selon lequel tout événement a une cause. De plus, certains phénomènes quantiques, comme l'intrication (entanglement), semblent violer la localité causale : la mesure d'une particule intriquée semble avoir un effet instantané sur l'état d'une particule distante, sans transmission de signal à une vitesse inférieure ou égale à celle de la lumière. Cela a conduit certains physiciens et philosophes à repenser profondément la notion de causalité dans le contexte quantique, en proposant par exemple des notions de « causalité contextuelle » ou de « causalité formelle »<ref>Philosophyjournal.spbu.ru (2020). « On Quantum Causality », ''Philosophy Journal SPbU'', 13(2), p. 180-195</ref>. ==Théories contemporaines de la causalité== ===Théories probabilistes=== Les théories probabilistes de la causalité cherchent à capturer l'idée que les causes ne nécessitent pas toujours leurs effets, mais les rendent plus probables. Patrick Suppes a développé une approche probabiliste selon laquelle un événement C est une cause prima facie d'un événement E si et seulement si : (1) C précède E dans le temps ; (2) la probabilité de C est supérieure à zéro ; (3) la probabilité de E sachant C est supérieure à la probabilité de E seul : P(E|C) > P(E)<ref>Suppes, P. (1970). ''A Probabilistic Theory of Causality'', Amsterdam : North-Holland Publishing Company</ref>. Cette approche permet de traiter les cas de causalité indéterministe (où une cause peut produire ou non son effet) et s'applique bien aux sciences qui utilisent des méthodes statistiques, comme l'épidémiologie ou les sciences sociales. Cependant, elle fait face à des difficultés : notamment, comment distinguer les corrélations dues à une cause commune des véritables relations causales ? Suppes introduit la notion de cause totale pour répondre à ce problème : C est la cause totale de E s'il n'existe aucune autre variable qui, conditionnellement à C, modifie la probabilité de E<ref>Reiss, J. (2016). « Suppes' Probabilistic Theory of Causality and its Application to Economics », ''Journal of Economic Methodology'', 23(4), p. 370-387</ref>. ===Théories mécanistes et pouvoirs causaux=== Les théories mécanistes de la causalité, développées notamment par Wesley Salmon, Stuart Glennan et Peter Machamer, proposent de comprendre la causalité en termes de processus causaux et de mécanismes. Un processus causal est un processus physique continu capable de transmettre une « marque » ou une quantité conservée (comme l'énergie ou la quantité de mouvement). Un mécanisme causal est un système organisé d'entités et d'activités qui produisent régulièrement un certain type d'effet<ref>Glennan, S. (1996). « Mechanisms and the Nature of Causation », ''Erkenntnis'', 44(1), p. 49-71</ref><ref>Machamer, P., Darden, L., & Craver, C. F. (2000). « Thinking about Mechanisms », ''Philosophy of Science'', 67(1), p. 1-25</ref>. Parallèlement, les théories des pouvoirs causaux (ou dispositions) soutiennent que les objets possèdent des pouvoirs intrinsèques qui sont activés dans certaines circonstances. La causalité ne serait pas une simple régularité entre événements distincts, mais l'exercice de ces pouvoirs. Cette approche, qui remonte à Aristote et a été défendue par Harré, Madden, Cartwright et Mumford, propose de concevoir les causes comme « disposant vers » leurs effets plutôt que les nécessitant strictement<ref>Mumford, S. & Anjum, R. L. (2011). « A Powerful Theory of Causation », in ''Getting Causes from Powers'', Oxford : Oxford University Press</ref>. Ces approches mécanistes et dispositionnalistes cherchent à réintroduire une notion robuste de causalité en ontologie, contre les approches réductionnistes ou éliminativistes. Elles mettent l'accent sur la production causale réelle plutôt que sur la simple régularité ou dépendance contrefactuelle. ===Causalité mentale et le monisme anomal de Davidson=== Un problème spécifique de la causalité se pose dans le domaine de la causalité mentale : comment les états mentaux (croyances, désirs, intentions) peuvent-ils causer des événements physiques (comme des actions corporelles) ? Donald Davidson propose une solution avec sa théorie du monisme anomal. Selon cette théorie, les événements mentaux sont identiques aux événements physiques (monisme), mais ils ne peuvent être subsumés sous des lois strictes reliant le mental et le physique (anomalisme). Les événements mentaux causent des événements physiques en vertu de leur identité avec des événements physiques qui tombent sous des lois physiques, mais ils ne peuvent être expliqués par des lois psychophysiques<ref>Davidson, D. (1970). « Mental Events », in ''Essays on Actions and Events'', Oxford : Clarendon Press, 1980</ref>. Cette position a été largement critiquée. Si les événements mentaux ne causent que parce qu'ils sont identiques à des événements physiques qui tombent sous des lois physiques, alors leurs propriétés mentales semblent causalement inertes (problème de l'épiphénoménalisme). Davidson répond que cette objection confond les événements (qui sont les relata de la relation causale) et les descriptions ou propriétés (qui figurent dans les explications causales). Un événement peut causer un autre événement en vertu de certaines de ses propriétés, même si cet événement pourrait aussi être décrit sous d'autres propriétés tombant sous d'autres lois<ref>De Pinedo, M. (2006). « Anomalous Monism : Oscillating between Dogmas », ''Synthese'', 148, p. 79-97</ref>. ==Conclusion== La causalité demeure une notion philosophiquement problématique malgré son omniprésence dans la pensée scientifique et ordinaire. Du questionnement aristotélicien sur la pluralité des causes à la critique humienne de la connexion nécessaire, de la tentative kantienne de sauver la causalité comme catégorie a priori aux débats contemporains sur la place de la causalité en physique fondamentale, l'histoire de la philosophie témoigne de la difficulté persistante à comprendre ce que signifie qu'une chose en cause une autre. Aucune théorie ne s'est imposée comme définitive. Les approches régularistes, contrefactuelles, probabilistes, mécanistes et dispositionnalistes offrent chacune des éclairages différents sur des aspects distincts de la causalité. Cette pluralité théorique reflète peut-être la pluralité des usages du concept de cause dans différents contextes : la causalité en physique fondamentale n'est peut-être pas la même que la causalité en biologie, en sciences sociales ou dans le sens commun. Plutôt qu'une notion univoque, la causalité apparaît comme un ensemble de notions apparentées mais distinctes, unifiées par l'idée générale de « faire une différence » ou de « production ». Comprendre la causalité exige donc non pas de trouver une définition unique et universelle, mais d'analyser les différentes formes que prend la relation causale dans différents domaines et de clarifier leurs présuppositions méthodologiques et ontologiques respectives. La causalité reste ainsi un concept fondamental mais pluriel, irréductible à une formule simple mais indispensable pour penser le changement, l'action et l'explication dans le monde. == Notes et références == {{references|colonnes=2}} ==Bibliographie== ; Sources primaires classiques * Aristote. ''Physique'', livre II, trad. P. Pellegrin, Paris, Flammarion, 2002. * Aristote. ''Métaphysique'', livre Δ, trad. M.-P. Duminil et A. Jaulin, Paris, Flammarion, 2008. * Thomas d'Aquin. ''Somme théologique'', I-II, q. 1, Paris, Cerf, 1984. * Descartes, René. ''Les Passions de l'âme'' (1649), in ''Œuvres'', éd. Adam-Tannery, Paris, Vrin, 1996. * Spinoza, Baruch. ''Éthique'' (1677), trad. B. Pautrat, Paris, Seuil, 1988. * Leibniz, Gottfried Wilhelm. ''Théodicée'' (1710), Paris, Flammarion, 1969. * Malebranche, Nicolas. ''De la recherche de la vérité'' (1674-1675), in ''Œuvres complètes'', éd. A. Robinet, Paris, Vrin, 1958-1984. * Hume, David. ''Traité de la nature humaine'' (1739-1740), livre I, partie III, trad. Ph. Saltel, Paris, Flammarion, 1995. * Hume, David. ''Enquête sur l'entendement humain'' (1748), section VII, trad. A. Leroy, Paris, Flammarion, 2006. * Kant, Immanuel. ''Critique de la raison pure'' (1781/1787), trad. A. Tremesaygues et B. Pacaud, Paris, PUF, 1993. * Mill, John Stuart. ''A System of Logic'' (1843), livre III, Londres, Longmans, 1961. ; Littérature secondaire contemporaine * Blanchard, Thomas (2016). « Physics and Causation », ''Philosophy Compass'', vol. 11, n° 5, p. 256-266. * Collins, John, Hall, Ned, & Paul, L. A. (eds.) (2004). ''Causation and Counterfactuals'', Cambridge, MA, MIT Press. * Davidson, Donald (1970). « Mental Events », in ''Essays on Actions and Events'', Oxford, Clarendon Press, 1980, p. 207-225. * De Pinedo, Manuel (2006). « Anomalous Monism : Oscillating between Dogmas », ''Synthese'', vol. 148, p. 79-97. * Dimech, Dominic K. (2019). « Quasi-Realism and Inductive Scepticism in Hume's Theory of Causation », ''Australasian Journal of Philosophy'', vol. 97, n° 1, p. 143-157. * Field, Hartry (2003). « Causation in a Physical World », in Michael Loux & Dean Zimmerman (eds.), ''The Oxford Handbook of Metaphysics'', Oxford, Oxford University Press, p. 435-460. * Frisch, Mathias (2020). « Causation in Physics », ''Stanford Encyclopedia of Philosophy'', https : //plato.stanford.edu/entries/causation-physics/ * Glennan, Stuart (1996). « Mechanisms and the Nature of Causation », ''Erkenntnis'', vol. 44, n° 1, p. 49-71. * Kannisto, Toni (2017). « Kant on the Necessity of Causal Relations », ''Kant-Studien'', vol. 108, n° 4, p. 645-668. * Le Ru, Véronique (2005). « La réception occasionaliste de Descartes : des Malebranchistes à l'Encyclopédie », ''Recherches sur Diderot et sur l'Encyclopédie'', n° 38, p. 83-100. * Lewis, David (1973). « Causation », ''Journal of Philosophy'', vol. 70, n° 17, p. 556-567. * Lewis, David (1979). « Counterfactual Dependence and Time's Arrow », ''Noûs'', vol. 13, n° 4, p. 455-476. * Lewis, David (2000). « Causation as Influence », ''Journal of Philosophy'', vol. 97, n° 4, p. 182-197. * Lin, Martin (2014). « Efficient Causation in Spinoza and Leibniz », in Michael Della Rocca (ed.), ''The Oxford Handbook of Spinoza'', Oxford, Oxford University Press, p. 167-193. * Machamer, Peter, Darden, Lindley, & Craver, Carl F. (2000). « Thinking about Mechanisms », ''Philosophy of Science'', vol. 67, n° 1, p. 1-25. * Mackie, John L. (1974). ''The Cement of the Universe : A Study of Causation'', Oxford, Clarendon Press. * Menzies, Peter (2001). « Counterfactual Theories of Causation », ''Stanford Encyclopedia of Philosophy'', https : //plato.stanford.edu/entries/causation-counterfactual/ * Mumford, Stephen & Anjum, Rani Lill (2011). ''Getting Causes from Powers'', Oxford, Oxford University Press. * Norton, John D. (2003). « Causation as Folk Science », ''Philosophers' Imprint'', vol. 3, n° 4, p. 1-22. * Reece, Bryan C. (2019). « Aristotle's Four Causes of Action », ''Australasian Journal of Philosophy'', vol. 97, n° 2, p. 213-227. * Reiss, Julian (2016). « Suppes' Probabilistic Theory of Causality and its Application to Economics », ''Journal of Economic Methodology'', vol. 23, n° 4, p. 370-387. * Rioux-Beaulne, Mitia (2018). « Fontenelle, Malebranche et les limites de la causalité », ''Revue philosophique de la France et de l'étranger'', vol. 143, n° 3, p. 365-388. * Ross, Don & Spurrett, David (2007). « Notions of Cause : Russell's Thesis Revisited », ''British Journal for the Philosophy of Science'', vol. 58, n° 1, p. 45-76. * Russell, Bertrand (1913). « On the Notion of Cause », ''Proceedings of the Aristotelian Society'', vol. 13, p. 1-26. * Suppes, Patrick (1970). ''A Probabilistic Theory of Causality'', Amsterdam, North-Holland Publishing Company. * Viljanen, Valtteri (2008). « Spinoza's Essentialist Model of Causation », ''Inquiry'', vol. 51, n° 4, p. 412-437. * Yalowitz, Steven (2005). « Anomalous Monism », ''Stanford Encyclopedia of Philosophy'', https : //plato.stanford.edu/entries/anomalous-monism/ {{Autocat}} kmb1vc55obll6ilg9lk14ak03arcmmd Dictionnaire de philosophie/Ghana 0 83066 768466 753840 2026-06-24T03:17:53Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768466 wikitext text/x-wiki {{DicoPhilo|- La philosophie ghanéenne récente -|lecture=oui}} La philosophie ghanéenne contemporaine constitue l'un des pôles les plus actifs et les plus influents de la philosophie africaine. Ancrée dans une longue tradition de réflexion critique qui remonte aux années 1940, elle continue de produire des contributions majeures aux débats philosophiques mondiaux tout en développant des approches conceptuelles distinctives. Ce panorama présente les principales figures, institutions, thèmes et orientations qui caractérisent la scène philosophique ghanéenne récente, en portant une attention particulière aux développements des deux dernières décennies. == Les héritiers d'une tradition philosophique établie == La philosophie ghanéenne contemporaine ne peut être comprise sans référence aux figures majeures qui ont fondé ce que l’on appelle aujourd’hui la « tradition philosophique de Legon ». Cette tradition, née à l’Université du Ghana (campus de Legon), se caractérise par une approche systématique et résolument humaniste de la philosophie dans le contexte africain. Elle cherche à articuler des positions qui ne soient ni simplement modernes ni postmodernes, mais « trans-modernes », c’est-à-dire capables d’emprunter de manière sélective et critique à des courants de pensée variés<ref>Martin Odei Ajei, « Trans-modernism and a Legon Tradition of African Philosophy », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 1-25.</ref>. Apparue dès les années 1940 et pleinement déployée après l’indépendance du Ghana en 1957, cette tradition intellectuelle a vu émerger plusieurs penseurs de stature internationale dont l’influence marque durablement la philosophie africaine et, au-delà, le débat philosophique mondial. === Kwasi Wiredu (1931-2022) : la décolonisation conceptuelle === Kwasi Wiredu, décédé le 6 janvier 2022 à l’âge de 90 ans, est souvent considéré comme l’un des plus grands philosophes africains de sa génération<ref>University of South Florida, « Kwasi Wiredu, 1931-2022 », en ligne : [https://www.usf.edu/arts-sciences/departments/philosophy/news/wiredu.aspx](https://www.usf.edu/arts-sciences/departments/philosophy/news/wiredu.aspx)</ref><ref>''Philosophy Now'', « Leading African Philosopher Dies, Aged 90 », n° 148, février/mars 2022.</ref>. Né à Kumasi en 1931 dans l’ancienne Gold Coast (actuel Ghana), il découvre la philosophie au collège Adisadel (1948-1952) en lisant Platon et Bertrand Russell<ref>University College Oxford, « In Memoriam Kwasi Wiredu », 10 février 2022.</ref>. Après un premier cycle à l’Université du Ghana, qu’il achève en 1958, il part étudier à University College, Oxford, où il prépare un B.Phil. sous la direction de Gilbert Ryle, avec P. F. Strawson comme tuteur de collège et Stuart Hampshire comme tuteur spécial<ref>University College Oxford, « In Memoriam Kwasi Wiredu », op. cit.</ref>. Sa thèse, intitulée ''Knowledge, Truth and Reason'', est achevée en 1960. Cette formation au cœur de la philosophie analytique britannique marque profondément son style et ses préoccupations. Gilbert Ryle, auteur de ''The Concept of Mind'' (1949), dont les analyses ont remis en cause le dualisme cartésien, exerce sur lui une influence décisive. Strawson, futur titulaire de la chaire de philosophie métaphysique à Oxford, décrit ainsi son étudiant ghanéen : « Je le trouvais remarquable : réservé et digne dans ses manières, doté d’une réelle subtilité et d’une certaine profondeur de pensée »<ref>University College Oxford, « In Memoriam Kwasi Wiredu », op. cit.</ref>. Après un bref passage au University College of North Staffordshire (aujourd’hui Université de Keele) en 1960-1961, Wiredu retourne au Ghana. Il y enseigne la philosophie à l’Université du Ghana pendant vingt-trois ans, y devient directeur de département puis professeur titulaire<ref>« Kwasi Wiredu », ''Wikipedia'', en ligne : [https://en.wikipedia.org/wiki/Kwasi_Wiredu](https://en.wikipedia.org/wiki/Kwasi_Wiredu)</ref>. En 1987, il accepte un poste de professeur distingué de philosophie à l’Université de Floride du Sud, à Tampa, où il demeurera jusqu’à sa retraite en 2010<ref>University of South Florida, « Kwasi Wiredu, 1931-2022 », op. cit.</ref>. Il est également professeur invité dans de nombreuses universités (UCLA, Ibadan, Richmond, Carleton College, Duke) et fellow au Woodrow Wilson International Center for Scholars et au National Humanities Center<ref>« Kwasi Wiredu », ''Wikipedia'', op. cit.</ref><ref>University of South Florida, « Kwasi Wiredu, 1931-2022 », op. cit.</ref>. De 1983 à 1998, il siège au comité de direction de la Fédération internationale des sociétés philosophiques<ref>« Kwasi Wiredu », ''Wikipedia'', op. cit.</ref>. La contribution philosophique majeure de Wiredu se cristallise sous le concept de « décolonisation conceptuelle », introduit dans une conférence de 1980 intitulée « Teaching and Research in African Philosophy: Some Suggestions »<ref>« Kwasi Wiredu », ''Wikipedia'', op. cit.</ref>. Par cette expression, il entend un projet méthodique de réexamen critique des cadres conceptuels occidentaux adoptés sans discernement, afin de dégager et de revivifier les ressources des épistémologies africaines indigènes<ref>Barry Hallen, ''Reading Wiredu'', Bloomington, Indiana University Press, 2021.</ref>. Il montre, par exemple, comment la simple traduction de notions occidentales de personne, de vérité ou de communauté dans les langues africaines, sans enquête préalable sur les catégories indigènes, engendre des confusions profondes. Dans son essai influent « Custom and Morality: A Comparative Analysis of Some African and Western Conceptions of Morals », il analyse minutieusement ces malentendus conceptuels nés de la transplantation non réfléchie d’idées occidentales dans un horizon Akan<ref>IDN, « Distinguished Philosopher Kwasi Wiredu Passes At 90 », 10 janvier 2022.</ref>. Wiredu estime que la philosophie africaine doit dépasser le stade de la simple mise en valeur des proverbes et de la « sagesse des anciens » pour se déployer dans les domaines formalisés de l’enquête philosophique : logique symbolique, philosophie des mathématiques, de la science, éthique normative, philosophie politique et sociale<ref>Barry Hallen, ''Reading Wiredu'', op. cit.</ref>. Mais cet exercice d’analyse rigoureuse doit, selon lui, être complété par ce qu’il nomme une approche « génétique », attentive aux conditions historiques, environnementales et culturelles qui ont donné naissance aux formes de pensée étudiées. Comprendre une conception Akan de la personne ou de la vérité, par exemple, implique d’en retracer la genèse dans des pratiques sociales, des institutions politiques et des systèmes de croyances déterminés<ref>Barry Hallen, ''Reading Wiredu'', op. cit., p. 96.</ref>. Parmi ses thèmes de prédilection, les concepts de vérité et d’esprit dans la culture Akan d’Afrique de l’Ouest occupent une place centrale. Ses ouvrages majeurs, tels que ''Philosophy and an African Culture'' (Cambridge University Press, 1980), ''Person and Community: Ghanaian Philosophical Studies'' (coédité avec Kwame Gyekye, 1992) et ''Cultural Universals and Particulars: An African Perspective'' (Indiana University Press, 1996), ont profondément marqué la discipline<ref>University of South Florida, « Kwasi Wiredu, 1931-2022 », op. cit.</ref>. En 2004, il édite ''A Companion to African Philosophy'' (Blackwell), qui devient un ouvrage de référence incontournable<ref>University of South Florida, « Kwasi Wiredu, 1931-2022 », op. cit.</ref>. Wiredu a également développé une théorie de la « démocratie consensuelle » inspirée des pratiques politiques traditionnelles Akan. Il soutient que, dans de nombreuses sociétés africaines précoloniales — qu’elles soient centralisées (avec roi ou chef) ou plus décentralisées —, la délibération politique fonctionnait sur le mode du consensus. Les détenteurs de l’autorité ne gouvernaient pas dans un isolement souverain, mais au terme de consultations prolongées et de compromis<ref>Barry Hallen, ''Reading Wiredu'', op. cit., p. 86-87.</ref>. Wiredu défend l’idée que : « la gouvernance consensuelle dans notre tradition était essentiellement démocratique ; que la forme majoritaire de démocratie observée dans les systèmes multipartites en Grande-Bretagne et aux États-Unis est radicalement antithétique à la fois à nos propres traditions de démocratie et aux complexités de notre situation contemporaine ; et que, bien que la base lignagère de nos systèmes politiques anciens ne puisse être réactivée telle quelle aujourd’hui, il demeure pratiquement envisageable de façonner une forme contemporaine de gouvernement non partisan fondée sur le principe du consensus »<ref>Barry Hallen, ''Reading Wiredu'', op. cit., p. 87.</ref>. Cette réflexion a alimenté d’importants débats sur les modèles institutionnels adaptés aux sociétés postcoloniales africaines. L’influence de Wiredu dépasse largement le cadre strict de la philosophie africaine. Nourri par Hume, Kant et Dewey, son travail se distingue par l’articulation originale d’une pensée africaine rigoureuse et des problématiques classiques de la philosophie analytique occidentale<ref>''Philosophy Now'', « Leading African Philosopher Dies, Aged 90 », op. cit.</ref>. Avec Paulin J. Hountondji (Bénin), Henry Odera Oruka (Kenya) et Peter O. Bodunrin (Nigeria), il contribue à la constitution de l’« école universaliste » de la philosophie africaine, qui défend l’idée que la philosophie en Afrique doit satisfaire aux mêmes exigences argumentatives et méthodologiques que partout ailleurs<ref>''Philosophy Now'', « Leading African Philosopher Dies, Aged 90 », op. cit.</ref>. Comme l’a souligné Joel Modiri, les écrits de Wiredu sur la pensée Akan et la décolonisation conceptuelle « nous ont mis au défi de résister toujours à l’assimilation non critique aux façons occidentales de penser »<ref>IDN, « Distinguished Philosopher Kwasi Wiredu Passes At 90 », op. cit.</ref>. Kwame Anthony Appiah, romancier et philosophe, résume ainsi l’estime qu’il lui portait : « L’un des plus grands philosophes africains est mort. Si vous ne le connaissez pas, vous devriez. C’était un homme d’une incroyable décence ; je le sais parce qu’il fut mon premier directeur de département »<ref>IDN, « Distinguished Philosopher Kwasi Wiredu Passes At 90 », op. cit.</ref>. La contribution de Wiredu à la philosophie africaine et mondiale demeure difficile à surestimer : sa notion de décolonisation conceptuelle continue d’inspirer plusieurs générations de chercheurs. === Kwame Gyekye (1939-2019) : communautarisme modéré et philosophie de la personne === Kwame Gyekye (1939-2019) constitue l’autre grand pilier de la philosophie ghanéenne moderne. Ses travaux sur la conception Akan de la personne et de la communauté ont exercé une influence durable bien au-delà du seul champ de la philosophie africaine<ref>Kwame Gyekye, ''Tradition and Modernity: Philosophical Reflections on the African Experience'', Oxford, Oxford University Press, 1997.</ref>. Formé à l’Université du Ghana, puis à l’étranger, Gyekye devient l’un des penseurs africains les plus respectés de sa génération. Son ouvrage majeur, ''An Essay on African Philosophical Thought: The Akan Conceptual Scheme'' (1re éd. 1987, éd. révisée 1995), propose une analyse systématique de la métaphysique, de l’épistémologie et de l’éthique Akan<ref>Kwame Gyekye, ''An Essay on African Philosophical Thought: The Akan Conceptual Scheme'', éd. révisée, Philadelphie, Temple University Press, 1995.</ref>. ''Tradition and Modernity: Philosophical Reflections on the African Experience'' (1997) examine, quant à lui, les tensions et les possibilités de dialogue entre valeurs traditionnelles africaines et exigences de la modernité<ref>Kwame Gyekye, ''Tradition and Modernity'', op. cit.</ref>. La contribution la plus discutée de Gyekye est sa théorie du « communautarisme modéré ». Il la fonde sur trois thèses principales : la nature sociale et rationnelle de l’individu, la reconnaissance de droits individuels irréductibles, et la suprématie morale de la communauté comme cadre d’épanouissement de la personne. La communauté joue un rôle constitutif dans la formation de la personnalité : l’être humain ne naît pas dans l’isolement, mais toujours déjà inséré dans un réseau de relations, ce qui atteste la dimension intrinsèquement relationnelle de la personne. Le débat célèbre qui l’oppose à Ifeanyi Menkiti est devenu un point de référence incontournable. Menkiti, dans une perspective qualifiée de communautarisme radical, soutient que la communauté « confère » la personnalité à l’individu, de sorte que l’identité personnelle est dérivée et secondaire. Gyekye, au contraire, défend l’idée que la tradition africaine reconnaît une valeur intrinsèque à l’individu<ref>Kwame Gyekye, ''Tradition and Modernity'', op. cit., p. 35-76.</ref>. Il mobilise notamment le proverbe Akan « Tous les êtres humains sont des enfants de Dieu ; personne n’est enfant de la terre » (''Nnipa nyinaa ye Onyame mma; obiara nni asase ba'') pour montrer que la personne est conçue comme un être théomorphe, portant en elle un reflet du divin<ref>Kwame Gyekye, ''An Essay on African Philosophical Thought'', op. cit., p. 143-146.</ref>. Le communautarisme modéré de Gyekye cherche ainsi à concilier droits individuels et responsabilités sociales, à équilibrer forces communautaires et autonomie personnelle. Les droits appartiennent, selon lui, « principalement et irréductiblement » à l’individu et sont le moyen par lequel celui-ci exprime ses talents, ses capacités et son identité. Mais ces droits ne sont pas absolus : ils peuvent être limités lorsqu’ils entrent en conflit avec des valeurs communautaires fondamentales telles que la paix, l’harmonie, la stabilité, la solidarité et les réciprocités mutuelles. C’est cette articulation délicate entre valeur de la communauté et dignité de l’individu qui a suscité un vaste débat. Plusieurs critiques, comme J. O. Famakinwa, ont mis en doute le caractère véritablement « modéré » de cette position, estimant que l’écart avec le communautarisme radical n’est peut-être pas aussi prononcé que le suggère Gyekye<ref>J. O. Famakinwa, « How Moderate is Kwame Gyekye’s Moderate Communitarianism? », ''Thought and Practice'', vol. 2, n° 2, 2010, p. 65-77.</ref>. D’autres auteurs ont relevé certaines tensions internes dans sa manière d’articuler les notions de personne, personnalité et communauté, créant un certain flou conceptuel<ref>Hasskei Mohammed Majeed, « The Nexus between Person, Personhood, and Community in Kwame Gyekye’s Philosophy », diverses éditions.</ref>. Ces discussions témoignent toutefois de la fécondité de son projet et de l’importance de ses analyses pour les débats contemporains sur l’individualisme, le communautarisme et les droits humains. Loin de se limiter à la philosophie politique et sociale, Gyekye a aussi œuvré dans d’autres domaines. Son livre ''Arabic Logic: Ibn al-Tayyib on Porphyry’s Eisagoge'' (1979) manifeste une solide compétence en philosophie médiévale islamique<ref>Kwame Gyekye, ''Arabic Logic: Ibn al-Tayyib on Porphyry’s Eisagoge'', Albany, State University of New York Press, 1979.</ref>. Dans ''Tradition and Modernity'', il aborde encore des questions d’éthique appliquée, de corruption politique et de légitimité de l’autorité dans les contextes africains postcoloniaux<ref>Kwame Gyekye, ''Tradition and Modernity'', op. cit.</ref>. === Kwame Anthony Appiah : cosmopolitisme et identité globale === Kwame Anthony Akroma-Ampim Kusi Appiah, né le 8 mai 1954 à Londres, incarne la dimension internationale et cosmopolite de la philosophie ghanéenne contemporaine<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', Londres, Routledge, 2021, p. 14.</ref>. Fils de Joseph Emmanuel Appiah (1918-1990), homme politique et avocat ghanéen, et de Peggy Appiah (née Cripps, 1921-2006), écrivaine britannique, il grandit entre l’Angleterre et le Ghana. Selon son propre témoignage, à vingt-et-un ans, il avait passé approximativement dix années au Ghana, dix en Angleterre, et une année entre la France, l’Allemagne, la Suisse et quelques autres pays<ref>Great Transition, « The Cosmopolitan Impulse in an Entangled World: Kwame Anthony Appiah », 27 octobre 2021.</ref>. Cette trajectoire biographique, marquée par la circulation et le croisement des cultures, façonne profondément sa vision du monde. Ses parents, eux-mêmes cosmopolites, recevaient au Ghana des amis venus de tous les horizons. Des personnalités comme Vijaya Lakshmi Pandit (sœur de Jawaharlal Nehru), l’écrivain américain Richard Wright ou l’intellectuel caribéen C. L. R. James fréquentaient leur maison. L’université, dans le Ghana non aligné de l’époque, attirait des enseignants venus aussi bien de l’ancien bloc soviétique et de la Chine que de ce que l’on appelait alors « l’Occident »<ref>Great Transition, « The Cosmopolitan Impulse in an Entangled World », op. cit.</ref>. Cette immersion précoce dans un milieu véritablement transnational se prolonge dans l’histoire familiale récente : mariages et alliances lient sa famille à la Norvège, au Nigeria, à la Namibie, à la Russie et aux États-Unis<ref>Great Transition, « The Cosmopolitan Impulse in an Entangled World », op. cit.</ref>. Professeur de philosophie et de droit à l’Université de New York, Appiah a élaboré une philosophie du cosmopolitisme qui puise à la fois dans les traditions grecques antiques, africaines et afro-américaines<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 6-7.</ref>. Dans la préface de ''In My Father’s House'' (1992), il explique avoir reçu de son père le « défi » et le « don » d’attachements multiples : Asante, ghanéen, africain, chrétien, etc. Loin d’y voir une source de déchirement, il les considère comme une richesse et une « abondance » identitaire<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 6.</ref>. Cette position liminaire, entre plusieurs appartenances, se reflète dans une œuvre résolument interdisciplinaire, à la croisée de la philosophie, de la littérature, des études américaines et africaines, de l’histoire intellectuelle et des débats contemporains<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 6.</ref>. L’œuvre d’Appiah interroge les identités raciales, les normes éthiques et les frontières culturelles, en montrant comment se construisent, se figent ou se défont les identités de croyance, de couleur, de pays ou de classe<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 72.</ref>. Dans ''Cosmopolitanism: Ethics in a World of Strangers'' (2006), il défend l’idée que nos obligations morales dépassent de beaucoup le cercle étroit de la citoyenneté partagée et impliquent de prendre au sérieux les pratiques et croyances d’autrui, sans jamais perdre de vue la valeur inconditionnelle de la vie humaine<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 57.</ref><ref>Appiah.net, « Cosmopolitanism », [https://appiah.net/books/cosmopolitanism/](https://appiah.net/books/cosmopolitanism/)</ref>. S’inspirant des cyniques grecs du IVe siècle av. J.-C., premiers à formuler l’idéal d’une citoyenneté « mondiale », Appiah rappelle que le cosmopolitisme a soutenu certaines des grandes avancées morales des Lumières, comme la Déclaration des droits de l’homme de 1789 ou le projet kantien d’une « société des nations »<ref>Appiah.net, « Cosmopolitanism », op. cit.</ref>. Pour lui, le cosmopolitisme repose sur deux idées étroitement liées : d’une part, nous avons des obligations envers des personnes auxquelles nous ne sommes unis par aucun lien particulier (préoccupation universelle) ; d’autre part, nous devons respecter et honorer la diversité légitime des formes de vie humaines<ref>''Cosmopolitanism: Ethics in a World of Strangers'', résumé et discussions sur Goodreads.</ref>. La métaphore centrale d’Appiah est celle de la conversation. Il conçoit le cosmopolitisme comme un processus de dialogue continu visant la compréhension mutuelle, refusant à la fois les tendances à l’universalisation forcée (contre-cosmopolitisme fondamentaliste) et un relativisme qui rendrait toute discussion vaine. « Si nous ne pouvons rien apprendre les uns des autres sur ce qu’il est juste de penser, de ressentir et de faire, alors la conversation entre nous sera sans intérêt », écrit-il, soulignant que la reconnaissance de la diversité ne doit pas conduire à l’abandon de toute prétention à la vérité ou à la critique<ref>''Cosmopolitanism: Ethics in a World of Strangers'', op. cit., p. 31.</ref>. Dans ''In My Father’s House: Africa in the Philosophy of Culture'' (1992), Appiah examine de façon critique les constructions de la « race » et du panafricanisme. Il montre comment certains intellectuels noirs de la diaspora ont, eux aussi, « inventé » une certaine Afrique pour répondre à leurs propres besoins politiques et symboliques<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 23-24.</ref>. Analysant la figure d’Alexander Crummell (1819-1898), il met en lumière les ambiguïtés d’un panafricanisme fondé sur l’idée d’une destinée commune des peuples d’Afrique, pensée sur le mode d’une appartenance raciale homogène<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 24.</ref>. Appiah distingue soigneusement le « racialisme » (croyance en l’existence de races naturelles dotées de traits partagés) du racisme proprement dit. Le racialisme n’est pas nécessairement agressif, bien qu’il repose sur des prémisses contestables ; il peut toutefois se muer en racisme selon les contextes. Appiah différencie ensuite un racisme extrinsèque, qui hiérarchise les groupes raciaux et leur attribue des capacités morales ou intellectuelles inégales, et un racisme intrinsèque, qui privilégie systématiquement les membres de son propre groupe racial pour la seule raison qu’ils lui appartiennent<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 24-26.</ref>. Lauréat en 2024 du prestigieux prix John W. Kluge, qui distingue des contributions majeures aux sciences humaines, Appiah incarne la reconnaissance internationale de la philosophie ghanéenne<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 61.</ref>. Son œuvre aborde, entre autres, l’histoire des révolutions morales (''The Honor Code''), la formation intellectuelle de W. E. B. Du Bois (''Lines of Descent''), les promesses et limites de l’« comme si » dans la pensée moderne (''As If''), ou encore les apports des neurosciences et de la psychologie cognitive à la compréhension de l’éthique de la vertu (''Experiments in Ethics'')<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 8.</ref>. Au fil de cette diversité thématique, un fil directeur se dessine : l’analyse des identités sociales et de leur déconstruction, sous l’angle de la philosophie morale et du raisonnement critique. Appiah place habituellement l’éthique avant la politique : pour lui, la réflexion politique doit se laisser guider par des exigences morales réfléchies<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 8.</ref>. === L’héritage collectif et la transmission intergénérationnelle === Ces trois figures majeures — Wiredu, Gyekye et Appiah — ont contribué ensemble à façonner ce que Martin Odei Ajei appelle la « tradition de Legon » en philosophie africaine. Plusieurs traits distinctifs caractérisent cette tradition et continuent d’influencer la philosophie ghanéenne contemporaine. D’abord, elle se distingue par la rigueur analytique et la clarté conceptuelle, héritées pour partie de la formation de ces philosophes dans la tradition analytique britannique, tout en demeurant profondément enracinée dans les contextes culturels africains. Wiredu, formé à Oxford auprès de Ryle, Strawson et Hampshire, a intégré les méthodes d’analyse conceptuelle les plus exigeantes à une approche génétique des formes de pensée africaines<ref>Barry Hallen, ''Reading Wiredu'', op. cit.</ref>. Gyekye et Appiah, chacun à sa manière, ont également mis en œuvre des outils conceptuels sophistiqués pour traiter des questions ancrées dans les expériences africaines. Ensuite, cette tradition se caractérise par un souci constant des questions pratiques de politique, d’éthique et de développement social. La théorie de la démocratie consensuelle de Wiredu répond à des interrogations concrètes sur les modèles de gouvernance adaptés aux sociétés africaines contemporaines<ref>Barry Hallen, ''Reading Wiredu'', op. cit., p. 81-93.</ref>. Gyekye, en réfléchissant à la tension entre tradition et modernité, vise à éclairer les choix normatifs auxquels sont confrontées les sociétés africaines en mutation<ref>Kwame Gyekye, ''Tradition and Modernity'', op. cit.</ref>. Appiah, en abordant les questions d’identité raciale et de cosmopolitisme, cherche à fournir des outils conceptuels pour orienter l’action dans un monde globalisé<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit.</ref>. Par ailleurs, la tradition de Legon adopte une posture « trans-moderne » au sens proposé par Ajei : elle refuse de se laisser enfermer dans l’alternative simple entre modernité et postmodernité. Consciente du fait que les sociétés africaines ont été façonnées par des couches successives d’influences — précoloniales, coloniales, postcoloniales, modernes et « traditionnelles » —, elle considère que la tâche de la philosophie est moins de choisir entre ces héritages que de les articuler de façon critique et créative<ref>Martin Odei Ajei, « Trans-modernism and a Legon Tradition of African Philosophy », op. cit.</ref>. Enfin, cette tradition accorde une place centrale au projet de décolonisation intellectuelle — non pas sous la forme d’un rejet global de la pensée occidentale, mais comme examen attentif des cadres conceptuels hérités et redécouverte des ressources propres aux épistémologies africaines. Wiredu a donné l’impulsion initiale avec la notion de décolonisation conceptuelle<ref>« Kwasi Wiredu », ''Wikipedia'', op. cit.</ref>. Gyekye, en mettant en lumière la richesse du schème conceptuel Akan, a montré comment une tradition locale peut nourrir des débats philosophiques généraux<ref>Kwame Gyekye, ''An Essay on African Philosophical Thought'', op. cit.</ref>. Appiah, en déconstruisant les catégories de race et d’« identité africaine », a montré que la décolonisation passe aussi par une réflexion critique sur les images de l’Afrique produites par les Africains eux-mêmes et par la diaspora noire<ref>Christopher J. Lee, ''Kwame Anthony Appiah'', op. cit., p. 14-34.</ref>. La transmission de cet héritage à la génération actuelle de philosophes ghanéens ne s’effectue pas de manière mécanique. Des penseurs comme Caesar Atuire, Martin Odei Ajei, Nancy Myles ou Richmond Kwesi, parmi d’autres, se situent dans le prolongement de cette tradition tout en la transformant. Ils étendent le champ des questions aux enjeux de la bioéthique globale, des technologies émergentes, du genre ou de la justice globale, tout en maintenant l’exigence d’une philosophie à la fois conceptuellement rigoureuse et contextuellement pertinente. La tradition philosophique de Legon apparaît ainsi comme un héritage vivant, en constant remaniement, plutôt que comme un canon figé. Les œuvres de Wiredu, Gyekye et Appiah ont fourni les assises sur lesquelles la philosophie ghanéenne contemporaine continue de bâtir. Elles montrent qu’une tradition philosophique authentiquement africaine peut être à la fois profondément enracinée dans des contextes culturels particuliers et universellement signifiante, critique des héritages coloniaux et ouverte aux dialogues interculturels, rigoureuse dans ses méthodes et engagée face aux défis concrets de son temps. == Les figures contemporaines et leurs contributions == La génération actuelle de philosophes ghanéens poursuit et enrichit l'héritage des pionniers comme Kwasi Wiredu, Kwame Gyekye et Kwame Anthony Appiah, tout en ouvrant de nouveaux chantiers de recherche qui témoignent d'une remarquable vitalité intellectuelle. Ces philosophes contribuent de manière significative aux débats philosophiques mondiaux tout en restant profondément ancrés dans les réalités et les préoccupations du continent africain. === Caesar Alimsinya Atuire : bioéthique africaine et solidarité globale === Caesar Alimsinya Atuire, professeur de philosophie et d'éthique au département de philosophie et de classiques de l'Université du Ghana, s'est imposé comme l'une des voix majeures de la bioéthique africaine contemporaine<ref>Caesar Atuire, PhD, Department of Bioethics and Humanities, University of Washington, disponible sur https://depts.washington.edu/bhdept/caesar-atuire-phd</ref>. Actuellement professeur d'éthique de la santé mondiale à l'Université d'Oxford, où il occupe le poste de responsable de l'éthique et de la gouvernance pour le MSc en médecine tropicale et santé internationale, et codirecteur associé d'Oxford Global Health, Atuire détient également un professorat adjoint en philosophie à l'Université du Ghana et est instructeur affilié au département de bioéthique et d'humanités de l'Université de Washington<ref>Professor Caesar Atuire, Global Health Ethics, University of Oxford, disponible sur https://www.globalhealth.ox.ac.uk/our-researchers/caesar-atuire</ref>. Son parcours intellectuel est singulier. Initialement formé en génie civil à l'Imperial College de Londres, il s'est ensuite orienté vers la philosophie et la théologie, obtenant un doctorat en philosophie et en éthique à Rome avec une thèse sur le suicide<ref>Caesar Atuire, PhD, op. cit.</ref>. Cette formation interdisciplinaire a nourri une approche de la bioéthique qui intègre à la fois les dimensions conceptuelles et empiriques. Sur le plan conceptuel, Atuire travaille à revisiter les cadres conceptuels sous-jacents à la bioéthique en puisant dans des idées philosophiques africaines et non africaines qui abordent les inégalités dans les relations gouvernant les approches actuelles de la santé mondiale, avec un regard vers de nouvelles frontières éthiques, la décolonisation et la pluriversalité<ref>Professor Caesar Atuire, Global Health Ethics, op. cit.</ref>. En 2019, Atuire a coédité avec d'autres chercheurs le volume ''Bioethics in Africa: Theories and Praxis'' (Vernon Press), qui présente des problèmes bioéthiques d'un point de vue africain<ref>Caesar Atuire, PhD, op. cit.</ref>. Ce volume constitue une contribution majeure à la littérature bioéthique en offrant des perspectives africaines authentiques sur des questions qui sont souvent traitées exclusivement à partir de cadres conceptuels occidentaux. Ses recherches et publications apportent des voix et des perspectives africaines à la conversation sur la santé mondiale et les questions éthiques, et ses travaux ont été publiés dans des revues prestigieuses telles que ''The Lancet'', ''BMJ Ethics'', ''BMJ Global Health'', ''The Hastings Center Report'', ''Developing World Bioethics'', ''Transcultural Psychiatry'' et le ''Journal of African Cultural Studies''<ref>Caesar Atuire, PhD, op. cit.</ref>. L'une des contributions les plus significatives d'Atuire à la philosophie contemporaine est son développement, en collaboration avec Nancy Jecker de l'Université de Washington, d'une approche de la justice en santé mondiale inspirée de l'éthique africaine de l'Ubuntu<ref>Nancy S. Jecker et Caesar A. Atuire, « Realizing Ubuntu in Global Health: An African Approach to Global Health Justice« , ''Public Health Ethics'', vol. 15, n° 3, 2022, p. 256-267</ref>. Dans leur article « Realizing Ubuntu in Global Health: An African Approach to Global Health Justice« publié en 2022 dans ''Public Health Ethics'', Atuire et Jecker articulent les exigences éthiques pour gouverner ce qu'ils appellent un « village de santé mondiale », en s'inspirant de l'éthique de l'Ubuntu pour formuler des conceptions africaines de la solidarité<ref>Nancy S. Jecker et Caesar A. Atuire, « Realizing Ubuntu in Global Health« , op. cit.</ref>. L'Ubuntu, souvent traduit par « humanité » ou « dignité humaine », englobe des dimensions à la fois ontologiques et normatives. Sur le plan ontologique, il est exprimé par des maximes telles que « une personne est une personne à travers d'autres personnes » (''umuntu ngumuntu ngabantu'') et « je suis parce que nous sommes », soulignant l'interdépendance humaine fondamentale<ref>Nancy S. Jecker et Caesar A. Atuire, « Realizing Ubuntu in Global Health« , op. cit.</ref>. Sur le plan normatif, l'Ubuntu prescrit une vie harmonieuse avec autrui, caractérisée par la sollicitude et l'attention mutuelles<ref>Nancy S. Jecker et Caesar A. Atuire, « Realizing Ubuntu in Global Health« , op. cit.</ref>. Cette conception a des implications profondes pour la manière dont nous conceptualisons les obligations morales dans un monde globalisé et interconnecté. Les travaux d'Atuire et de ses collaborateurs ont exploré l'application de l'Ubuntu à des questions concrètes de santé mondiale, telles que l'allocation des vaccins contre la COVID-19, la résistance aux antimicrobiens et l'accès aux soins de santé. Dans leur article « A Just Transition for Antimicrobial Resistance: Planning for an Equitable and Sustainable Future with Antimicrobial Resistance« publié en 2024 dans ''The Lancet'', ils examinent comment les réponses à la résistance aux antimicrobiens peuvent être mal adaptées aux contextes locaux, négliger les inégalités historiques ou écarter les systèmes de connaissances marginalisés<ref>S. R. Varadan, C. I. R. Chandler, K. Weed, S. M. Ahmed, C. Atuire, D. Batheja et al., « A Just Transition for Antimicrobial Resistance: Planning for an Equitable and Sustainable Future with Antimicrobial Resistance« , ''The Lancet'', vol. 403, n° 10446, 2024, p. 2766-2767</ref>. Ils argumentent qu'une philosophie de l'Ubuntu révèle des formes d'injustice qui seraient autrement invisibles dans les cadres conceptuels occidentaux dominants. Au niveau empirique, Atuire a conçu un programme de formation en éthique clinique pour les étudiants en soins infirmiers au Ghana basé sur des cas réels, a siégé dans des comités d'examen institutionnels (IRB), et a contribué à la conception et à l'enseignement du premier Master en bioéthique à l'Université du Ghana<ref>Professor Caesar Atuire, Global Health Ethics, op. cit.</ref>. Il a dirigé des recherches empiriques sur les conceptualisations et l'éthique des soins de santé mentale, en particulier en relation avec les personnes qui détiennent des croyances culturelles et religieuses sur l'esprit<ref>Professor Caesar Atuire, Global Health Ethics, op. cit.</ref>. Ces recherches abordent des questions complexes telles que la pratique de l'enchaînement de personnes atteintes de maladies mentales graves dans des camps de prière au Ghana, et les conflits entre groupes internationaux et guérisseurs religieux et spirituels concernant ces pratiques<ref>Nancy S. Jecker et Caesar A. Atuire, « Bioethics in Africa: A Contextually Enlightened Analysis of Three Cases« , ''Developing World Bioethics'', 2021</ref>. La reconnaissance internationale d'Atuire témoigne de l'influence de ses contributions. Il est actuellement président de l'Association internationale de bioéthique pour la période 2024-2026, membre du groupe de travail de l'OMS sur l'éthique et la gouvernance de la COVID-19, membre du comité de pilotage du Forum mondial sur la bioéthique dans la recherche, et membre principal du groupe de travail lié au CDC Afrique sur un cadre africain pour l'éthique de la recherche lors d'épidémies de maladies infectieuses émergentes et réémergentes<ref>Caesar Atuire, AABHL Conference Speaker, disponible sur https://aabhlconference.com/speaker/caesar-atuire/</ref>. Il dirige actuellement une équipe internationale dans le cadre d'une bourse Wellcome Discovery Award visant à explorer les conceptualisations de la solidarité et à concevoir un indice de solidarité pour classer les bailleurs de fonds en santé mondiale<ref>Caesar Atuire, PhD, op. cit.; Professor Caesar Atuire, Global Health Ethics, op. cit.</ref>. Au-delà de sa vie académique, Atuire dirige depuis 2003 une ONG, Amicus Onlus (www.amicusonlus.org), qui fournit des soins de santé aux communautés rurales de la région centrale du Ghana, offre une formation professionnelle aux jeunes marginalisés et aide les immigrants illégaux de retour d'Europe à se réinstaller au Ghana<ref>Caesar Atuire, PhD, op. cit.</ref>. Cette dimension pratique de son engagement complète son engagement philosophique pour un monde plus éthique et démontre une cohérence entre sa pensée théorique et son action dans le monde. Parmi ses publications récentes les plus importantes figurent : « Bioethics Must Consider War as a Public Health Crisis: Reply to Commentaries« (2025), « Creating Different Global Health Futures: Mapping the Health Research Ecosystem and Taking Decolonial Action« (2025), « Emergent Personhood: Reply to Critics« (2025), « Can Solidarity in Global Health Curb the Next Outbreak? A Commentary on Mpox« (2025), et « From Just Transitions to Just Transformations: Observations from Aotearoa New Zealand in Addressing the Human Wellbeing Impacts of Climate Change« (2025)<ref>Professor Caesar Atuire, Global Health Ethics, op. cit.</ref>. === Martin Odei Ajei : philosophie politique africaine et théorie de la justice === Martin Odei Ajei, professeur associé de philosophie à l'Université du Ghana, se distingue par ses travaux en philosophie africaine et en philosophie politique, avec un accent particulier sur les philosophies africaines de libération et les discours de justice mondiale<ref>Martin Odei Ajei, The Neubauer Collegium, University of Chicago, disponible sur https://neubauercollegium.uchicago.edu/people/martin-odei-ajei</ref>. Formé en philosophie à l'Université de Stockholm, à l'Université du Ghana et à l'Université d'Afrique du Sud, où il a obtenu son doctorat en 2006, Ajei a développé une approche philosophique qui s'enracine dans les traditions intellectuelles ghanéennes tout en s'engageant de manière critique avec la théorie politique contemporaine<ref>Martin Ajei, Google Scholar, disponible sur https://scholar.google.com/citations?user=BGguAtYAAAAJ&hl=en</ref>. Sa thèse de doctorat, intitulée « Africa's Development: The Imperatives of Indigenous Knowledge and Values« (2007), constitue une contribution majeure à la réflexion sur le développement africain, et a été citée plus de 77 fois, témoignant de son influence dans le domaine<ref>Martin Ajei, Google Scholar, op. cit.</ref>. Dans cette œuvre, Ajei examine les systèmes de connaissances autochtones et la bonne gouvernance au Ghana, en prenant pour exemple la société Akan traditionnelle, et développe une critique des paradigmes de développement imposés de l'extérieur qui négligent les ressources intellectuelles et morales des sociétés africaines elles-mêmes<ref>Martin Odei Ajei, « Indigenous Knowledge Systems and Good Governance in Ghana: The Traditional Akan Socio-Political Example« , ''Organization for Social Science Research in Eastern and Southern Africa'', 2001</ref>. L'une des contributions théoriques les plus importantes d'Ajei concerne la démocratie consensuelle de Kwasi Wiredu et ses perspectives de mise en pratique en Afrique. Dans son article « Kwasi Wiredu's Consensual Democracy: Prospects for Practice in Africa« , publié en 2016 dans le ''European Journal of Political Theory'', Ajei examine de manière critique la viabilité pratique de cette conception de la démocratie qui repose sur le consensus plutôt que sur le principe majoritaire<ref>Martin Odei Ajei, « Kwasi Wiredu's Consensual Democracy: Prospects for Practice in Africa« , ''European Journal of Political Theory'', vol. 15, n° 4, 2016, p. 445-466</ref>. Cet article, cité plus de 30 fois, constitue une contribution significative au débat sur les formes appropriées de gouvernance démocratique en Afrique, un débat qui oppose ceux qui préconisent l'adoption de modèles de démocratie libérale occidentale et ceux qui cherchent à développer des modèles de gouvernance enracinés dans les traditions politiques africaines. Ajei a également contribué de manière significative à la compréhension de la tradition philosophique ghanéenne elle-même. Dans son article « Trans-modernism and a Legon Tradition of African Philosophy« , publié en 2018 dans le ''Legon Journal of the Humanities'', il trace les contours de ce qu'il appelle la « tradition de Legon » en philosophie africaine, identifiant les contributions de Kwasi Wiredu, William E. Abraham et Kwame Gyekye comme formant une approche cohérente et systématique de la philosophie dans le contexte africain<ref>Martin Odei Ajei, « Trans-modernism and a Legon Tradition of African Philosophy« , ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 1-25</ref>. Cette tradition, selon Ajei, se caractérise par une approche « trans-moderne » qui emprunte de manière sélective et critique aux différents courants de pensée sans être simplement moderne ni postmoderne, mais capable d'intégrer des éléments de modernisme tout en rejetant certaines caractéristiques postmodernistes<ref>Martin Odei Ajei, « Trans-modernism and a Legon Tradition of African Philosophy« , op. cit.</ref>. Dans son chapitre « Toward a Tradition of Ghanaian Political Philosophy« , publié en 2019 dans ''The Oxford Handbook of Comparative Political Theory'', Ajei élabore les perspectives normatives de Kwame Nkrumah, Kwasi Wiredu, William E. Abraham et Kwame Gyekye sur trois thèmes centraux : la pertinence de la tradition pour la modernité, la forme appropriée de démocratie comme moyen de légitimer le pouvoir politique en Afrique, et le statut relatif de la personne et de la communauté<ref>Martin Odei Ajei, « Toward a Tradition of Ghanaian Political Philosophy« , ''The Oxford Handbook of Comparative Political Theory'', 2019, p. 125</ref>. Cette contribution systématique à la philosophie politique ghanéenne démontre la richesse et la cohérence d'une tradition intellectuelle qui mérite une reconnaissance plus large dans les débats de philosophie politique comparative. Ajei a également édité en 2016 le volume ''Disentangling Consciencism: Essays on Kwame Nkrumah's Philosophy'' (Lexington Books), avec une préface de Kwame Gyekye<ref>Martin Odei Ajei (éd.), ''Disentangling Consciencism: Essays on Kwame Nkrumah's Philosophy'', Lanham, MD, Lexington Books, 2016</ref>. Ce volume, publié pour célébrer le cinquantième anniversaire de la publication du ''Consciencism'' de Nkrumah (1964), rassemble des essais de philosophes africains et internationaux qui examinent de manière critique les dimensions métaphysiques, éthiques et politiques de la pensée de Nkrumah. Dans son propre chapitre, « Justice and the Retrieval of the African Self: The Perspective of Consciencism« , Ajei développe l'idée de « self-retrievism » (l'auto-recouvrement) comme une vertu urgente pour les sociétés africaines contemporaines et comme condition nécessaire d'une conception souhaitable de la justice pour l'avenir africain<ref>Martin Odei Ajei, « Justice and the Retrieval of the African Self: The Perspective of Consciencism« , dans Martin Odei Ajei (éd.), ''Disentangling Consciencism'', op. cit., p. 229-245</ref>. Dans cet essai, Ajei soutient qu'une conception relationnelle de la justice, enracinée dans le cadre éthique africain traditionnel et dans la vision de la personne comme être intrinsèquement relationnel, diffère des théories prééminentes de la personne et de la société qui soutiennent la notion occidentale de justice<ref>Martin Odei Ajei, « Justice and the Retrieval of the African Self« , op. cit., p. 230-232</ref>. Il défend la thèse que le « self-retrievism », un état particulier d'être qu'il définit comme la revendication d'une vision progressive et digne de l'africanité, est la vertu la plus urgente des institutions sociales africaines et une condition nécessaire pour une conception souhaitable de la justice pour l'avenir africain<ref>Martin Odei Ajei, « Justice and the Retrieval of the African Self« , op. cit., p. 229, 234-236</ref>. En 2018, Ajei a également publié un article important intitulé « Educating Africans: Perspectives of Ghanaian Philosophers« dans la revue ''Phronimon'', dans lequel il réfléchit aux principes fondamentaux et aux stratégies pour l'enseignement supérieur en Afrique<ref>Martin Odei Ajei, « Educating Africans: Perspectives of Ghanaian Philosophers« , ''Phronimon'', vol. 19, 2018, p. 1-15</ref>. Il y soutient que depuis le début des années 1940, les philosophes ghanéens ont avancé des perspectives sans ambiguïté sur la politique éducative en Afrique, bien que ces perspectives n'aient pas encore trouvé d'expression dans la formulation des politiques publiques<ref>Martin Odei Ajei, « Educating Africans« , op. cit.</ref>. Ajei plaide pour une approche « sankofaiste » de la conceptualisation de l'éducation, qui incorpore ces perspectives philosophiques ghanéennes. Le concept de Sankofa, symbolisé par l'oiseau Akan qui regarde en arrière tout en avançant, représente l'idée qu'il faut retourner chercher dans le passé ce qui est précieux pour construire l'avenir. Ajei a également exploré des questions d'ontologie et de droits humains, notamment dans son article « Ontology and Human Rights« publié en 2019 dans le ''South African Journal of Philosophy''<ref>Martin Odei Ajei, « Ontology and Human Rights« , ''South African Journal of Philosophy'', 2019</ref>. En collaboration avec d'autres chercheurs, il a travaillé sur les conceptualisations africaines du soi et de la conscience. Son article coécrit avec C. Grills, « African-Centered Conceptualizations of Self and Consciousness: The Akan Model« , publié par Sage Publications en 2002, explore comment le modèle Akan de la conscience et du soi diffère des conceptualisations occidentales et quelles implications ces différences ont pour la psychologie et la philosophie de l'esprit<ref>C. Grills et Martin Ajei, « African-Centered Conceptualizations of Self and Consciousness: The Akan Model« , Sage Publications, 2002</ref>. Plus récemment, Ajei a exploré la question du statut moral en s'inspirant des perspectives africaines. En collaboration avec Caesar Atuire et Nancy Jecker, il a publié en 2022 deux articles importants dans ''Philosophy & Technology'' : « The Moral Standing of Social Robots: Untapped Insights from Africa« et « Two Steps Forward: An African Relational Account of Moral Standing« <ref>Nancy S. Jecker, Caesar A. Atuire et Martin Odei Ajei, « The Moral Standing of Social Robots: Untapped Insights from Africa« , ''Philosophy & Technology'', vol. 35, n° 2, 2022, article 34 ; Nancy S. Jecker, Caesar A. Atuire et Martin Odei Ajei, « Two Steps Forward: An African Relational Account of Moral Standing« , ''Philosophy & Technology'', vol. 35, n° 2, 2022, article 38</ref>. Dans ces articles, les auteurs argumentent que les conceptions africaines relationnelles de la personne offrent des insights précieux pour penser le statut moral des entités non-humaines comme les robots sociaux, démontrant ainsi comment les ressources conceptuelles de la philosophie africaine peuvent enrichir les débats philosophiques sur les technologies émergentes. === Nancy Oppongwaa Myles : personnisme et démocratie africaine === Nancy Oppongwaa Myles, docteure en philosophie de l'Université d'Utrecht aux Pays-Bas, est coordinatrice de la pensée critique et du raisonnement pratique à l'Université du Ghana<ref>Dr. Nancy Myles B. Gyamfi, Department of Philosophy and Classics, University of Ghana, disponible sur https://www.ug.edu.gh/phcl.ug/people/dr-nancy-myles-b-gyamfi</ref>. Ses recherches portent sur la philosophie sociale et politique, et elle travaille en particulier sur ce qu'elle appelle le « personisme » (''personism''), une position philosophique innovante qui cherche à dépasser le débat entre individualisme et communautarisme<ref>Nancy O. Myles, Google Scholar, disponible sur https://scholar.google.com/citations?user=KxPOhs8AAAAJ&hl=en</ref>. Dans son article séminal « 'The Individual' in the Individualism-Communitarianism Debate: In Defense of Personism« , publié en 2018 dans le ''Legon Journal of the Humanities'', Myles défend une conception qui reconnaît à la fois la valeur intrinsèque de l'individu et l'importance des relations communautaires<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism-Communitarianism Debate: In Defense of Personism« , ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 157-189</ref>. Cet article, qui a été cité au moins 16 fois et qui figure dans sa thèse de doctorat, constitue une contribution théorique majeure à la philosophie sociale africaine<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate: In Defense of Personism« , Academia.edu, disponible sur https://www.academia.edu/60202096/</ref>. L'argument central de Myles est que le débat entre individualisme et communautarisme repose sur une confusion conceptuelle fondamentale : l'obfuscation du concept de « l'individu » (''the individual'') avec l'individualité des personnes. Adoptant principalement une approche analytique, son article apporte une clarification à la substance du débat en se concentrant sur la pensée communautarienne occidentale. Elle préconise de faire de « la personne » le centre d'attention car le « personisme » englobe nécessairement à la fois l'individualité et la communalité<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 157-158</ref>. Selon Myles, le personisme conçoit l'individualité et la communalité comme des dispositions ou dimensions duales d'une seule entité — « la personne » — qui est naturellement et nécessairement à la fois individuelle et relationnelle, et interconnectée à différents niveaux avec d'autres personnes, tout cela simultanément<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 178</ref>. Cette conception diffère des doctrines de l'individualisme et du communautarisme, qui toutes deux conçoivent « l'individu » comme une entité dont les droits doivent être accommodés et respectés, pour différentes raisons certes, par une supposée « communauté » ou « des communautés » pour certains, qui est une autre entité. Pour Myles, la différence fondamentale réside dans le fait que si la communalité est conçue comme « la communauté », cela en fait une question de choix quant à savoir si les personnes voudraient appartenir à « la communauté ». Mais le personisme défend la thèse que la communalité, comme l'individualité, n'est pas optionnelle pour la personne. Autrement dit, pour la thèse personniste, la personne ne choisit pas d'être individuelle. Elle ne choisit pas non plus d'être communale (c'est-à-dire relationnelle). Elle est à la fois individuelle et communale en dehors de son choix<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 178</ref>. Ce n'est donc pas une question de médiation entre deux entités distinctes pour donner lieu à des arguments libéralistes ou de « communautarisme modéré » tels que ceux avancés par le philosophe africain renommé Kwame Gyekye. Myles critique la position de Gyekye, qui défend le « communautarisme modéré », en soutenant que cette position n'est pas aussi modérée que Gyekye le croit, et que l'écart supposé entre sa vision et la vision « communautarienne radicale » qu'il critique pourrait ne pas être aussi large qu'il le pense<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 178-179, citant J. O. Famakinwa, 2011</ref>. Le « communautarisme modéré » de Gyekye, selon Myles, exprime l'idée que bien que la société africaine soit de caractère communautarien, elle accorde également une certaine individualité et/ou des droits individuels. Mais la position de Gyekye a été critiquée pour son incohérence dans ses conceptions de « personne, personnalité et communauté » en raison de « difficultés existant dans les propres arguments de Gyekye », entraînant un manque de clarté<ref>Hasskei Mohammed Majeed, « The Nexus between Person, Personhood, and Community in Kwame Gyekye's Philosophy« , cité dans Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 179</ref>. Myles soutient également que l'argument du personisme est que l'individualité d'une personne n'est pas seulement inaccessible et non transférable aux autres ; elle est en fait inaliénable. Pas même la personne elle-même ne peut nier ou se défaire de son individualité comprise dans ce sens puisque toute tentative de suppression de son individualité serait elle-même l'expression même de cette individualité<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 179</ref>. Pourtant, le personisme insiste sur le fait que la force de la communalité ou relationnalité naturelle et nécessaire d'une personne ne peut pas non plus être minimisée : d'abord avec elle-même ; ensuite avec les « autres significatifs » immédiats tels que la famille, la « communauté communautarienne » et ses systèmes, structures, langue, histoire, culture et formes de vie particulières essentielles qui contribuent à former son identité ; mais ensuite aussi avec le monde extérieur et plusieurs autres de différentes manières dont certaines pourraient être distantes et pourtant très significatives<ref>Nancy Oppongwaa Myles, « 'The Individual' in the Individualism/Communitarianism Debate« , op. cit., p. 179-180</ref>. Myles s'intéresse également aux questions de démocratie en Afrique et plaide pour un retour critique aux principes d'humanisme, de communalité et de recherche du consensus qui ont évolué dans le contexte africain traditionnel<ref>Nancy Oppongwaa Myles, « Remembering Democracy: A Reflection on an African Tradition« , 2022</ref>. Dans son article « Remembering Democracy: A Reflection on an African Tradition« publié en 2022, elle examine le système socio-politique africain traditionnel en contraste avec l'héritage colonial de la démocratie comme système de gouvernance et prescrit la décolonisation conceptuelle comme réponse aux nombreux défis variés de la politique en Afrique aujourd'hui<ref>Nancy Oppongwaa Myles, « Remembering Democracy« , disponible sur https://jocap.domuni.eu/jocap/article/download/remembering-democracy-a-reflection-on-an-african-tradition/16/53</ref>. Elle soutient qu'un tel retour critique rendrait la pratique de la démocratie meilleure en Afrique contemporaine, compte tenu de son caractère multinational et de l'histoire de l'impact colonial prolongé<ref>Dr. Nancy Myles B. Gyamfi, op. cit.; Nancy Oppongwaa Myles, « Remembering Democracy« , op. cit.</ref>. Myles a également coécrit avec Martin Ajei un chapitre sur la personnalité, l'autonomie et le consentement éclairé dans le volume ''Bioethics in Africa'', explorant comment les conceptions africaines de la personne affectent la compréhension de l'autonomie individuelle dans les contextes médicaux<ref>Dr. Nancy Myles B. Gyamfi, op. cit.</ref>. Cette contribution démontre la pertinence des réflexions philosophiques sur la personne pour des questions pratiques de bioéthique et d'éthique médicale. === Richmond Kwesi : philosophie du langage et démocratie consensuelle === Richmond Kwesi, maître de conférences et responsable du bureau des cours connexes de l'Université du Ghana (UGRCs), a obtenu son doctorat en 2017 à l'Université du Cap en Afrique du Sud<ref>Dr. Richmond Kwesi, Department of Philosophy and Classics, University of Ghana, disponible sur https://www.ug.edu.gh/phcl.ug/people/dr-richmond-kwesi</ref>. Ses intérêts de recherche se situent en philosophie analytique, en philosophie du langage et en pensée philosophique africaine traditionnelle. Ses publications en philosophie du langage portent sur la métaphore, la vérité et l'assertion, tandis qu'en philosophie africaine il a publié sur la démocratie consensuelle, l'empiricalisme de Kwasi Wiredu et le Consciencisme de Kwame Nkrumah<ref>Dr. Richmond Kwesi, op. cit.</ref>. Lauréat du prix d'essai Kwasi Wiredu sur l'épistémologie et la métaphysique africaines financé par la Carnegie Corporation à l'Université de Dar es Salaam en 2019, Kwesi a également reçu une bourse de deux ans de la Fondation Andrew Mellon (2018-2020) pour ses recherches sur la démocratie consensuelle<ref>Dr. Richmond Kwesi, op. cit.</ref>. Il a récemment édité un numéro spécial sur la démocratie consensuelle africaine pour la revue ''The Philosophical Forum'', publié par Wiley-Blackwell, rassemblant diverses perspectives sur ce thème central de la philosophie politique africaine<ref>Dr. Richmond Kwesi, op. cit.</ref>. Ses articles récents incluent « The Will to Consensus« (2024) et « People and Power in an African Consensual Democracy« (2021), qui explorent les dimensions théoriques et pratiques de la démocratie consensuelle dans le contexte africain<ref>Dr. Richmond Kwesi, op. cit.</ref>. Ces travaux s'inscrivent dans la continuation et l'approfondissement des idées de Kwasi Wiredu sur la démocratie consensuelle, qui repose sur la pratique traditionnelle Akan et argumente que le consensus était plus fidèle à l'esprit démocratique que le vote majoritaire. Kwesi a également contribué au volume ''Disentangling Consciencism: Essays on Kwame Nkrumah's Philosophy'' édité par Martin Odei Ajei, avec un chapitre intitulé « The Logic of Consciencism« , dans lequel il examine la structure logique de l'argumentation de Nkrumah<ref>Richmond Kwesi, « The Logic of Consciencism« , dans Martin Odei Ajei (éd.), ''Disentangling Consciencism'', op. cit., p. 185-197</ref>. Dans ses travaux sur la philosophie du langage, Kwesi adopte une approche analytique rigoureuse. Ses publications incluent des articles critiquant l'argument phénoménologique de Davidson contre les prétentions cognitives de la métaphore, ainsi que des explorations de l'articulation inférentielle des assertions métaphoriques. Ces travaux en philosophie du langage s'inscrivent dans la tradition analytique tout en restant attentifs aux questions spécifiquement africaines et démontrent la capacité des philosophes ghanéens à contribuer aux débats techniques en philosophie analytique contemporaine. Kwesi a également bénéficié d'une bourse Bechs-Africa à l'Université américaine du Caire et du programme Erasmus+ de mobilité du personnel à l'Université d'Utrecht<ref>Dr. Richmond Kwesi, op. cit.</ref>. Ces expériences internationales enrichissent sa recherche philosophique en l'exposant à différentes approches et en créant des opportunités de collaboration interdisciplinaire et interculturelle. === Hasskei Mohammed Majeed : philosophie de l'esprit africaine === Hasskei Mohammed Majeed, chercheur à l'Université du Ghana, se distingue par ses travaux en philosophie de l'esprit africaine et en philosophie de la religion<ref>Hasskei Mohammed Majeed, Google Scholar, disponible sur https://scholar.google.com/citations?user=GEUEdskAAAAJ&hl=en</ref>. Il a consacré plusieurs études à la question de la réincarnation dans la philosophie africaine, explorant notamment les conceptions Akan de la personne et leur rapport aux questions vie-mort. Son article « The Nexus between Person, Personhood, and Community in Kwame Gyekye's Philosophy« examine les relations conceptuelles entre ces notions dans la pensée de Gyekye<ref>Hasskei Mohammed Majeed, « The Nexus between Person, Personhood, and Community in Kwame Gyekye's Philosophy« , cité dans le contexte</ref>. Majeed a également publié sur le communautarisme modéré, répondant aux critiques formulées par divers auteurs, et sur la rationalité de la religion traditionnelle Akan. Ses recherches plus récentes portent sur le mal, la mort et certaines conceptions africaines de Dieu. Majeed a travaillé sur les questions d'ontologie et d'épistémologie dans la pensée Akan, notamment sur la question du « paranormal » et sur la rationalité de la religion traditionnelle africaine. Dans son article « Reincarnation: A Question in the African Philosophy of Mind« (2017), il examine comment la croyance en la réincarnation soulève des questions fondamentales sur l'identité personnelle, la continuité du soi et la nature de la conscience. Majeed a également critiqué ce qu'il appelle le « quasi-physicalisme » dans la philosophie Akan, remettant en question les interprétations qui tentent de réduire les concepts spirituels Akan à des phénomènes purement matériels. Ses travaux explorent les composantes de la personne dans la pensée Akan, notamment le concept de ''sunsum'' (esprit), et leur relation avec les questions de destinée, de libre arbitre et de responsabilité morale. === Husein Inusah : décolonisation épistémique === Husein Inusah, professeur associé à l'Université de Cape Coast, travaille sur l'épistémologie, la pensée critique, la philosophie des sciences et la philosophie de l'esprit<ref>Husein Inusah, Google Scholar, disponible sur https://scholar.google.com/citations?user=GEUEdskAAAAJ&hl=en</ref>. Son travail se concentre notamment sur la décolonisation épistémique dans l'enseignement supérieur africain. Dans son article « Epistemic Decolonisation in African Higher Education: Beyond Current Curricular and Pedagogical Reformation« publié en 2023, il va au-delà des réformes curriculaires et pédagogiques actuelles pour proposer une véritable transformation épistémique. Inusah a également exploré les vertus intellectuelles de la sagesse autochtone africaine à travers les proverbes Akan, ainsi que la question de la relativité épistémique en philosophie africaine. Son article « Who is Afraid of Epistemic Relativism? Disentangling African Philosophy from the 'Universalist' Entrapment« cherche à libérer la philosophie africaine du piège universaliste. Il s'intéresse également à l'infinitisme en épistémologie et a publié plusieurs articles sur la démocratie consensuelle de Wiredu et la rationalité consensuelle. Inusah souligne que la décolonisation épistémique dans l'enseignement supérieur africain nécessite des transformations qui vont au-delà des simples réformes curriculaires et pédagogiques. Il s'agit de repenser fondamentalement les structures de production et de validation des connaissances, ainsi que les rapports de pouvoir qui sous-tendent ces structures. === Stephen Nkansah Morgan : éthique et technologies émergentes === Stephen Nkansah Morgan explore les intersections entre l'éthique africaine et les nouvelles technologies. Dans son article « African Ethics and Online Communities: An Argument for a Virtual Communitarianism« publié en 2021, il propose d'appliquer les principes communautariens africains aux communautés en ligne<ref>Stephen Nkansah Morgan, « African Ethics and Online Communities: An Argument for a Virtual Communitarianism« , cité dans le contexte</ref>. Il a également travaillé sur les technologies de reproduction assistée et l'éthique Akan autochtone, examinant de manière critique les implications éthiques de ces technologies dans le contexte africain. Morgan démontre que la philosophie africaine n'est pas simplement tournée vers le passé ou préoccupée uniquement par les questions traditionnelles, mais qu'elle s'engage activement avec les défis éthiques les plus contemporains. Ses recherches suggèrent que l'éthique africaine peut offrir des ressources précieuses pour penser les relations sociales dans l'espace virtuel et pour aborder les questions éthiques soulevées par les technologies de la reproduction. === Conclusion === Les figures contemporaines de la philosophie ghanéenne présentées ici — Caesar Atuire, Martin Ajei, Nancy Myles, Richmond Kwesi, Hasskei Mohammed Majeed, Husein Inusah et Stephen Nkansah Morgan — témoignent de la vitalité et de la diversité de la pensée philosophique au Ghana aujourd'hui. Leurs contributions couvrent un large éventail de domaines, de la bioéthique à la philosophie politique, de la philosophie du langage à l'épistémologie, de la philosophie de l'esprit à l'éthique des technologies émergentes. Ces philosophes partagent plusieurs caractéristiques communes. Premièrement, ils sont tous profondément ancrés dans les traditions philosophiques ghanéennes et africaines tout en s'engageant de manière critique avec les débats philosophiques mondiaux. Deuxièmement, ils démontrent une rigueur académique exceptionnelle et une maîtrise des méthodes philosophiques contemporaines, qu'elles soient analytiques, phénoménologiques ou critiques. Troisièmement, ils manifestent un engagement profond avec les questions sociales et politiques contemporaines, refusant de séparer la philosophie théorique de ses implications pratiques pour les sociétés africaines. Leurs travaux illustrent également la capacité de la philosophie ghanéenne à contribuer de manière significative aux conversations philosophiques mondiales tout en restant pertinente pour les contextes africains. Que ce soit dans le développement d'une bioéthique africaine basée sur l'Ubuntu, dans l'articulation d'une théorie du personisme qui transcende le débat individualisme-communautarisme, dans l'exploration de la démocratie consensuelle comme alternative viable aux modèles de démocratie libérale, ou dans l'application de l'éthique africaine aux technologies émergentes, ces philosophes démontrent que la philosophie africaine n'est pas simplement une variation régionale de la philosophie occidentale, mais une tradition intellectuelle autonome avec ses propres questions, méthodes et insights. == Les institutions et structures de recherche == === L'Université du Ghana à Legon : le centre névralgique de la philosophie ghanéenne === L'Université du Ghana à Legon constitue le centre névralgique de la philosophie ghanéenne contemporaine. Fondée en 1948, l'université a développé depuis plus de sept décennies une tradition philosophique dynamique et internationalement reconnue. ==== Le département de philosophie et de classiques ==== Le département de philosophie et de classiques, fondé en 1963, offre des programmes de premier cycle (B.A. Philosophy & Classics) et de cycles supérieurs (Master et PhD)<ref>University of Ghana, « B.A. Philosophy & Classics », disponible sur https://www.ug.edu.gh/node/140</ref>. Le département constitue l'un des plus anciens centres d'enseignement et de recherche en philosophie d'Afrique subsaharienne. Depuis sa création, il a produit plusieurs générations de philosophes qui ont marqué le paysage intellectuel africain et mondial. La philosophie y est définie comme l'amour de la sagesse, permettant de développer une attitude réflexive et critique envers la vie en façonnant notre vision du monde et nos relations avec les autres, tout en nous fournissant des raisons adéquates pour soutenir nos opinions, jugements et décisions<ref>University of Ghana, « B.A. Philosophy & Classics », op. cit.</ref>. La philosophie est également présentée comme une méthode interdisciplinaire permettant de produire des connaissances et la vérité dans tous les domaines d'étude en examinant de manière critique le sens et la clarté des concepts, la valeur probante des preuves ou informations, l'adéquation logique des hypothèses et des inférences, ainsi que les méthodes d'investigation. Le département emploie plusieurs enseignants-chercheurs de renommée internationale. Parmi les membres actuels ou récents du département figurent Martin Odei Ajei (professeur associé), Emmanuel Ifeanyi Ani (maître de conférences), Caesar Alimsinya Atuire (professeur adjoint), Richmond Kwesi (maître de conférences), et Hasskei Mohammed Majeed (maître de conférences)<ref>University of Ghana, Pure Research Portal, « Department of Philosophy and Classics - Profiles », disponible sur https://pure.ug.edu.gh/en/organisations/department-of-philosophy-and-classics-2/persons/</ref>. Le département organise régulièrement des conférences internationales et des séminaires. En 2025, il a co-organisé avec l'Association Classique du Ghana la première conférence internationale des étudiants diplômés sur les classiques et la philosophie, avec le soutien de la Princeton Africa World Initiative et de la Faculté des Classiques de l'Université de Cambridge<ref>PhilEvents, « 1st International Graduate Conference (Classical Association of Ghana) », disponible sur https://philevents.org/event/show/135601</ref>. Dans les années 2000, le département a honoré ses figures fondatrices. En 2007, il a organisé une cérémonie en l'honneur du professeur Kwame Gyekye pour célébrer le 40e anniversaire de son doctorat de Harvard et ses 40 années de service au département et à l'Université du Ghana<ref>GhanaDot, « Legon Philosophy Department honours Kwame Gyekye », disponible sur http://www.ghanadot.com/personalities.profkyekye.061509.html</ref>. La citation soulignait que Gyekye n'était pas seulement un érudit et philosophe, mais également un enseignant, ami, mari, père et grand-père, et saluait ses contributions exceptionnelles à l'étude de la philosophie qui ont tracé un chemin pour les générations futures d'étudiants et d'universitaires. Au cours de ses quatre décennies de service à l'université, Gyekye a occupé plusieurs postes administratifs importants, notamment Vice Master de l'Akuafo Hall, directeur du département de philosophie, doyen de la Faculté des arts, doyen de l'École de recherche et des études supérieures, ainsi que président de plusieurs conseils d'administration. ==== L'Institute of African Studies (IAS) ==== L'Institute of African Studies de l'Université du Ghana, établi en 1961 et formellement inauguré en octobre 1963 par le premier président du Ghana, Kwame Nkrumah, constitue un autre pilier institutionnel majeur pour la philosophie ghanéenne<ref>University of Ghana, Institute of African Studies, « About the Institute », disponible sur https://ias.ug.edu.gh</ref><ref>Wikipedia, « Institute of African Studies », disponible sur https://en.wikipedia.org/wiki/Institute_of_African_Studies</ref>. Le mandat de l'institut est de mener des recherches et un enseignement sur les peuples et le patrimoine culturel de l'Afrique et de diffuser les résultats. L'institut a toujours mis l'accent sur la publication et l'enseignement, particulièrement au niveau postdoctoral. Lors de son discours inaugural d'ouverture de l'institut, Kwame Nkrumah a posé un ensemble de questions fondamentales qui encapsulent l'histoire, la vision et la mission de l'institut, ainsi que le besoin d'embrasser l'érudition humaniste via la décolonisation de l'éducation : « Quel type d'Institut d'études africaines le Ghana veut-il et dont il a besoin ? De quelle manière le Ghana peut-il apporter sa propre contribution spécifique à l'avancement des connaissances sur les peuples et les cultures d'Afrique à travers l'histoire passée et à travers les problèmes contemporains ? Pour quel type de service préparons-nous les étudiants de cet Institut et de nos Universités ? Sommes-nous sûrs d'avoir établi ici la meilleure relation possible entre enseignants et étudiants ? Dans quelle mesure nos universités sont-elles identifiées aux aspirations du Ghana et de l'Afrique ? »<ref>Institute of African Studies, « About the Institute », op. cit.</ref>. Nkrumah a souligné la nécessité d'une réinterprétation et d'une nouvelle évaluation des facteurs qui constituent le passé africain. Il a reconnu franchement que les études africaines, sous la forme qu'elles ont été développées dans les universités et centres d'apprentissage en Occident, ont été largement influencées par les concepts des « études coloniales » à l'ancienne, et restent encore, dans une certaine mesure, sous l'ombre des idéologies et de la mentalité coloniales. « Une fonction essentielle de cet Institut doit sûrement être d'étudier l'histoire, la culture et les institutions, les langues et les arts du Ghana et de l'Afrique de nouvelles manières centrées sur l'Afrique — en toute liberté par rapport aux propositions et présuppositions de l'époque coloniale, et des distorsions de ces professeurs et chargés de cours qui continuent à faire des études européennes sur l'Afrique la base de cette nouvelle évaluation »<ref>Institute of African Studies, « About the Institute », op. cit.</ref>. La section Religions et Philosophie de l'institut mène des recherches et enseigne les dynamiques des cultures et philosophies religieuses autochtones en Afrique<ref>Institute of African Studies, « Religions and Philosophy Section », disponible sur https://ias.ug.edu.gh/content/religions-and-philosophy-section</ref>. Elle examine comment ces religions affectent la société et comment elles sont affectées par elle. La section étudie le changement religieux en se concentrant sur l'émergence de religions étrangères telles que l'Islam et le christianisme et leurs modes de diffusion et d'appropriation en Afrique. Elle examine également comment l'Islam, le christianisme dominant et ses ramifications — notamment les Nouveaux Mouvements Religieux (Églises indépendantes africaines, églises pentecôtistes et charismatiques) — impactent les religions et cultures autochtones et vice versa, délimitant les conflits et la coexistence des religions et cultures dans l'Afrique contemporaine. La section examine aussi la religion et la philosophie en relation avec des questions telles que la culture, le développement, la politique, le genre, l'éthique, la santé, la guérison et la médecine. En tant que section multidisciplinaire, ses approches reflètent l'expertise de son corps professoral, notamment sociologique, anthropologique, philosophique et théologique. Parmi les cours actuellement offerts dans la section pour les étudiants de troisième cycle figurent : Religion traditionnelle africaine, Islam et christianisme en Afrique, Fondements de la pensée africaine, et Religion et politique en Afrique. La section est également impliquée dans l'enseignement de certains cours au niveau du premier cycle, notamment : Culture et développement, Culture populaire africaine : festivals traditionnels et cérémonies funéraires, et Philosophie dans les cultures africaines. En février 2025, l'Institute of African Studies, en collaboration avec le département de philosophie et de classiques, a organisé une conférence publique sur le thème « Redéfinir une tradition philosophique à partir de l'expérience africaine », donnée par le professeur Elvis Imafidon de la School of Oriental and African Studies (SOAS) de l'Université de Londres<ref>Institute of African Studies, « Redefining a Philosophical Tradition from the African Experience », disponible sur https://ias.ug.edu.gh/content/redefining-philosophical-tradition-african-experience</ref>. Le professeur Imafidon, spécialiste reconnu de la philosophie africaine et président du Centre for Global and Comparative Philosophies à SOAS, a remis en question de manière critique le récit occidental dominant de la philosophie comme étant enracinée dans la textualité et l'auteur individuel. Ces caractéristiques, a-t-il soutenu, ont été injustement utilisées pour exclure les systèmes de pensée africains — en particulier ceux qui existaient avant le milieu du XXe siècle — d'être reconnus comme philosophie légitime. Il a proposé un cadre alternatif qui redéfinit une tradition philosophique comme un héritage cohérent ancré dans le sens fondamental de la philosophie — l'amour et la recherche de la sagesse — en soulignant que la philosophie africaine a toujours existé, soutenue par des efforts individuels et collectifs à travers les générations. L'institut abrite également plusieurs unités et installations importantes, notamment le Ghana Dance Ensemble (la compagnie nationale de danse originale), l'unité des publications, les archives J.H. Kwabena Nketia, une bibliothèque spécialisée, une section audiovisuelle avec plus de 3 000 enregistrements discographiques et vidéo et plus de 8 000 photographies, ainsi qu'un musée avec diverses collections incluant des poids d'or Asante<ref>Institute of African Studies, « About the Institute », op. cit.</ref>. ==== Le Maria Sibylla Merian Institute for Advanced Studies in Africa (MIASA) ==== Le Maria Sibylla Merian Institute for Advanced Studies in Africa (MIASA), créé en 2018 au Collège des sciences humaines de l'Université du Ghana, campus de Legon, constitue une infrastructure de recherche récente mais importante pour la philosophie ghanéenne<ref>MIASA, « About », disponible sur https://miasa.ug.edu.gh</ref>. MIASA est basé sur une collaboration entre l'Université du Ghana et un consortium de partenaires allemands — l'Université de Fribourg, l'Université Goethe de Francfort, le German Institute for Global and Area Studies (GIGA) et le German Historical Institute Paris (DHIP). L'institut est financé par le ministère fédéral allemand de l'Éducation et de la Recherche (BMBF), avec un cofinancement de l'Université du Ghana. MIASA est dédié au thème de la « gouvernance durable », définie comme l'interaction des règles informelles et formelles pour diriger les affaires publiques, intégrées dans des pratiques sociales, matérielles et culturelles historiquement contextualisées de la vie quotidienne<ref>MIASA, « About », op. cit.</ref>. Les trois axes de recherche de MIASA sont : la transformation environnementale durable, la gestion durable des conflits et la démocratie durable. L'institut couvre également des thèmes transversaux tels que la propriété et l'acquisition foncière, la migration et la mobilité, la restitution d'objets culturels acquis colonialement, les villes africaines et les droits humains. MIASA offre des bourses pour les chercheurs postdoctoraux seniors et juniors en sciences humaines et sociales. Les objectifs généraux de MIASA sont de travailler à la réduction des asymétries mondiales dans la production de connaissances et de combler le fossé culturel entre l'Afrique anglophone et francophone. MIASA sert de hub pour l'échange, le réseautage et la collaboration entre chercheurs de premier plan du Ghana, d'Allemagne, des continents africain et européen et au-delà. Outre son programme de bourses, MIASA organise un large éventail d'événements, notamment des conférences thématiques (au Ghana et dans d'autres pays africains), des conférences politiques, la conférence annuelle Anton Wilhelm Amo, ainsi que des ateliers pour les chercheurs en début de carrière d'Afrique tels que des ateliers d'écriture, des ateliers de publication et des ateliers sur les carrières universitaires féminines en Afrique. Les résultats clés de la recherche de MIASA sont publiés dans la série de documents de travail de l'institut (disponible sur UGSpace), sur le blog académique de MIASA et sous forme d'articles externes dans des revues et livres évalués par des pairs. MIASA a introduit en 2021 la conférence annuelle Anton Wilhelm Amo à l'Université du Ghana, en l'honneur du philosophe africain du XVIIIe siècle<ref>MIASA Blog, « Anton Wilhelm Amo Lecture, University of Ghana », disponible sur https://miasa.hypotheses.org/2317</ref>. La conférence sert l'un des objectifs clés de MIASA : contribuer à la décolonisation de la production de connaissances et à la justice épistémique. Pour les besoins de la conférence Anton Wilhelm Amo, MIASA collabore avec le département de philosophie et de classiques et l'Institute of African Studies de l'Université du Ghana. En tant qu'événement majeur de l'Université du Ghana, la conférence se tient au Great Hall du campus de Legon et est ouverte par une performance du Ghana Dance Ensemble. La première conférence Amo en 2021 a coïncidé avec le dévoilement de la plaque Anton Wilhelm Amo rénovée au département de philosophie et de classiques, qui avait été initialement offerte par l'Université de Halle dans les années 1970, l'alma mater d'Amo. En 2021, le professeur J. Obi Oguejiofor (Université Nnamdi Azikiwe) a présenté « The Significance of Anton Wilhelm Amo in Contemporary African Philosophy », qui a réfléchi sur l'histoire de la vie d'Amo et la perception de sa philosophie en Afrique de l'Ouest. En 2022, la professeure Sylvia Tamale (Université Makerere) a demandé dans sa conférence « Decolonising Knowledge Production in Africa » de repenser les pratiques de production de connaissances héritées sans critique, de contourner les gardiens intellectuels et de démocratiser l'espace épistémique. En 2023, le professeur Felwine Sarr (Université Duke) a abordé la question de « Building African Ecologies of Knowledge », invitant le public à apprécier la pluralité des connaissances qui vont au-delà d'une idée occidentale de ce qui est perçu comme connaissance ou non. === L'Université de Cape Coast === L'Université de Cape Coast constitue un autre pôle important pour la philosophie au Ghana, avec son département de classiques et philosophie. L'université a produit plusieurs philosophes influents, dont Husein Inusah, professeur associé qui travaille sur l'épistémologie, la pensée critique, la philosophie des sciences et la philosophie de l'esprit, avec un accent particulier sur la décolonisation épistémique dans l'enseignement supérieur africain. === Les réseaux et collaborations internationales === Les institutions philosophiques ghanéennes sont intégrées dans des réseaux internationaux de recherche et entretiennent des relations avec de nombreuses universités internationales. Les philosophes ghanéens participent régulièrement à des conférences internationales et occupent des postes dans des universités étrangères. Par exemple, Caesar Atuire est professeur d'éthique de la santé mondiale à l'Université d'Oxford tout en maintenant sa position à l'Université du Ghana. Kwame Anthony Appiah est professeur de philosophie et de droit à l'Université de New York. Martin Odei Ajei a été chercheur au Neubauer Collegium de l'Université de Chicago. Ces collaborations internationales enrichissent la philosophie ghanéenne en l'exposant à différentes approches et en créant des opportunités de dialogue interculturel et interdisciplinaire. Elles contribuent également à accroître la visibilité internationale de la philosophie ghanéenne et à assurer que les perspectives ghanéennes et africaines sont représentées dans les débats philosophiques mondiaux. === Les défis institutionnels === Malgré ces infrastructures impressionnantes, la philosophie ghanéenne fait face à plusieurs défis institutionnels. L'un des principaux défis concerne le financement de la recherche et le soutien institutionnel pour les jeunes chercheurs. Un autre défi majeur est la nécessité de renforcer les liens entre la recherche philosophique et les politiques publiques. Comme l'a souligné Martin Odei Ajei, depuis les années 1940, les philosophes ghanéens ont avancé des perspectives sans ambiguïté sur la politique éducative en Afrique, mais ces perspectives n'ont pas encore trouvé d'expression dans la formulation des politiques publiques<ref>Ajei, Martin Odei, « Educating Africans : Perspectives of Ghanaian Philosophers », ''Phronimon'', vol. 19, 2018, p. 1-15.</ref>. La question de la décolonisation de l'enseignement et de la production de connaissances reste également un chantier ouvert, nécessitant une transformation qui va au-delà des simples réformes curriculaires et pédagogiques pour repenser fondamentalement les structures de production et de validation des connaissances. == Les revues et plateformes de publication == La philosophie ghanéenne dispose d'une infrastructure éditoriale dynamique comprenant des revues nationales de grande qualité et une présence croissante dans les publications internationales. Cette infrastructure permet la dissémination de la recherche philosophique et contribue au rayonnement de la pensée ghanéenne dans les débats académiques mondiaux. === Le Legon Journal of the Humanities (LJH) === Le ''Legon Journal of the Humanities'' (LJH) constitue la plateforme de publication la plus importante pour la philosophie ghanéenne. Fondé en 1974, le LJH est une publication internationale à comité de lecture du Collège des sciences humaines de l'Université du Ghana<ref>Legon Journal of the Humanities, « About the Journal », disponible sur https://www.plutojournals.com/legon-journal-of-the-humanities/</ref><ref>University of Ghana, Legon Journal of the Humanities, disponible sur https://journals.ug.edu.gh/index.php/ljh</ref>. Le journal publie des articles de recherche originaux examinant les aspects culturels, historiques, philosophiques, linguistiques et créatifs de l'expérience humaine, avec un accent particulier sur les perspectives africaines. Le LJH accueille des approches interdisciplinaires de chercheurs établis et émergents du monde entier, publiant des articles de recherche, des critiques de livres et de films, ainsi que des entretiens<ref>Legon Journal of the Humanities, « About the Journal », op. cit.</ref>. Le journal est publié en ligne deux fois par an en tant que revue en libre accès en anglais et est indexé dans le Directory of Open Access Journals (DOAJ)<ref>Directory of Open Access Journals, « Legon Journal of the Humanities », disponible sur https://doaj.org/toc/2458-746X</ref>. Il présente occasionnellement des numéros thématiques coordonnés par des éditeurs invités, annoncés par des appels à contributions dans un numéro précédent du journal et/ou via des listes de diffusion. Le journal porte l'ISSN en ligne 2458-746X et l'ISSN imprimé 0855-1510. Il est disponible en texte intégral sur African Journals Online (AJOL) depuis 2008 (volume 19) et sur JSTOR depuis 2011 (volume 22)<ref>Mir@bel, « Legon Journal of the Humanities », disponible sur https://reseau-mirabel.info/revue/6116/Legon-Journal-of-the-Humanities</ref>. La revue fonctionne selon un modèle « diamant » sans frais de publication pour les auteurs (pas d'article processing charges ou APCs)<ref>Directory of Open Access Journals, « Legon Journal of the Humanities », op. cit.</ref>. Le LJH est consacré à l'étude des sciences humaines, conceptualisées de manière large pour couvrir non seulement les arts et les langues, mais également les disciplines des sciences sociales telles que les études culturelles, la géographie humaine, les affaires internationales, les études de gestion, les sciences politiques, la psychologie et la sociologie<ref>Legon Journal of the Humanities, « About the Journal », op. cit.</ref>. Cette approche interdisciplinaire permet au journal de servir de plateforme pour des méthodologies innovantes et des analyses critiques qui enrichissent le discours académique tout en abordant les complexités de l'expression humaine et de la production culturelle en Afrique et au-delà. L'éditrice en chef actuelle est la professeure associée Benedicta A. Lomotey. Le processus d'examen par les pairs est une double évaluation à l'aveugle, et le délai moyen de la soumission à la publication est de 24 semaines<ref>Researcher.Life, « Legon Journal of the Humanities: Impact Factor & More », disponible sur https://researcher.life/journal/legon-journal-of-the-humanities/26871</ref>. Tous les manuscrits doivent être soumis via le portail de soumission du LJH sur le système de gestion des revues de l'Université du Ghana<ref>University of Ghana, « Submissions | Legon Journal of the Humanities », disponible sur https://journals.ug.edu.gh/index.php/ljh/about/submissions</ref>. Le LJH dispose d'un processus de présélection interne où tout manuscrit soumis est d'abord examiné par l'équipe éditoriale. Si la soumission n'est pas adaptée à la revue, elle peut être rejetée à ce stade et ne passera pas à l'étape d'examen par les pairs. L'auteur peut recevoir des commentaires sur les publications qui pourraient être mieux adaptées et quelques commentaires initiaux pour améliorer la qualité du manuscrit. D'autres détails pris en compte lors du présélection initiale incluent l'utilisation correcte de la langue, l'évitement du plagiat et la conformité aux directives pour les auteurs du LJH. Le numéro actuel (Volume 36, numéro 1, 2025) a été produit avec le soutien financier de la Carnegie Corporation de New York à travers le projet Building A New Generation of Academics in Africa (BANGA-Africa) Phase IV de l'Université du Ghana<ref>University of Ghana, Legon Journal of the Humanities, vol. 36, n° 1, 2025</ref>. En 2023, le LJH a publié 11 articles couvrant divers domaines des sciences humaines et sociales. Le volume 29, numéro 2 de 2018 du LJH a été particulièrement important pour la philosophie ghanéenne, publiant notamment l'article fondateur de Martin Odei Ajei « Trans-modernism and a Legon Tradition of African Philosophy » ainsi que l'article de Nancy Oppongwaa Myles « 'The Individual' in the Individualism-Communitarianism Debate: In Defense of Personism »<ref>Ajei, Martin Odei, « Trans-modernism and a Legon Tradition of African Philosophy », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 1-25</ref><ref>Myles, Nancy Oppongwaa, « 'The Individual' in the Individualism-Communitarianism Debate: In Defense of Personism », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 157-189</ref>. Ces articles ont contribué de manière significative à la définition et à l'articulation de la tradition philosophique ghanéenne contemporaine. === Phronimon : Journal of the South African Society for Greek Philosophy and the Humanities === ''Phronimon'', bien qu'étant une revue sud-africaine, constitue une plateforme importante pour les philosophes ghanéens et africains en général. Publié par UNISA Press (University of South Africa Press), ''Phronimon'' est le journal bisannuel de la South African Society for Greek Philosophy and the Humanities<ref>University of South Africa, « Phronimon journal », disponible sur https://www.unisa.ac.za/sites/corporate/default/Colleges/Human-Sciences/Schools,-departments,-centres,-institutes-&-units/School-of-Humanities/Department-of-Philosophy,-Practical%C2%A0and-Systematic-Theology/Discipline-of-Philosophy/Phronimon-journal</ref><ref>Sabinet African Journals, « Phronimon », disponible sur https://journals.co.za/journal/phron</ref>. ''Phronimon'' publie des contributions scientifiques originales et justifiables (articles, discussions d'articles précédemment publiés et critiques de livres) dans le domaine de la philosophie et des sciences humaines en général, bien que la priorité soit donnée aux contributions dans le domaine de la philosophie grecque et des études grecques<ref>Ancient World Online, « Journal of the South African Society for Greek Philosophy and the Humanities », disponible sur http://ancientworldonline.blogspot.com/2011/01/open-access-journal-phronimon.html</ref>. Le journal publie en anglais, en afrikaans et en grec moderne. L'ISSN de ''Phronimon'' est 1561-4018 (imprimé) et 2413-3086 (en ligne). Le journal publie des travaux de haute qualité académique et encourage les articles qui répondent aux normes les plus élevées d'expertise philosophique tout en restant accessibles aux lecteurs d'un large éventail de disciplines philosophiques<ref>Sabinet African Journals, « Phronimon », op. cit.</ref>. Bien que la préférence soit accordée aux articles relatifs à la philosophie grecque ancienne, le comité de rédaction apprécie les contributions de chercheurs en sciences humaines dans leur ensemble avec l'intention de fournir un forum international pour la recherche interdisciplinaire, le débat et la discussion. Le journal encourage et poursuit activement la diversité des points de vue des contributeurs. Il n'est donc en aucun cas engagé envers une école de pensée, un parti, une méthode ou un style particulier au sein des sciences humaines. L'éditeur en chef actuel est le professeur Michael Cloete. Le journal est accrédité par le South African Department of Higher Education and Training. Tous les articles et articles de synthèse sont soumis à des évaluateurs nationaux et internationaux. Une référence efficace et détaillée des sources est d'une importance primordiale. Les articles sont examinés et vérifiés pour les références bibliographiques et toute preuve de plagiat avéré entraînera la non-publication. Les philosophes ghanéens ont régulièrement publié dans ''Phronimon''. Martin Odei Ajei y a notamment publié « Educating Africans: Perspectives of Ghanaian Philosophers » en 2018, un article important qui examine les perspectives des philosophes ghanéens sur la politique éducative en Afrique<ref>Ajei, Martin Odei, « Educating Africans: Perspectives of Ghanaian Philosophers », ''Phronimon'', vol. 19, 2018, p. 1-15</ref>. Cet article soutient que depuis les années 1940, les philosophes ghanéens ont avancé des perspectives sans ambiguïté sur la politique éducative en Afrique, bien que ces perspectives n'aient pas encore trouvé d'expression dans la formulation des politiques publiques. Le journal est disponible en ligne via plusieurs plateformes, notamment UNISA Press Journals, SciELO South Africa, et le dépôt institutionnel UPSpace de l'Université de Pretoria, qui a obtenu l'autorisation de la South African Society for Greek Philosophy and the Humanities de numériser tous les articles publiés dans ''Phronimon''<ref>University of Pretoria UPSpace, « Phronimon », disponible sur https://repository.up.ac.za/handle/2263/4136</ref>. === Le South African Journal of Philosophy (SAJP) === Le ''South African Journal of Philosophy'' (SAJP) est une revue trimestrielle à comité de lecture publiée par Taylor & Francis Online au nom de la Philosophical Society of South Africa<ref>Wikipedia, « South African Journal of Philosophy », disponible sur https://en.wikipedia.org/wiki/South_African_Journal_of_Philosophy</ref><ref>Taylor & Francis, « South African Journal of Philosophy », disponible sur https://www.tandfonline.com/journals/rsph20</ref>. Fondée en 1981, la revue est indexée dans le Thomson Reuters Arts and Humanities Index. L'objectif de la revue est de publier des contributions savantes originales dans tous les domaines de la philosophie à un niveau international. Le SAJP publie des contributions originales (articles, discussions d'articles précédemment publiés, articles de synthèse et critiques de livres) dans tous les domaines de la philosophie<ref>Sabinet African Journals, « South African Journal of Philosophy », disponible sur https://journals.co.za/journal/sajop</ref>. Bien qu'étant une revue sud-africaine, le SAJP est ouvert aux contributions de philosophes du monde entier, y compris du Ghana. Cependant, l'histoire du SAJP et de sa société hôte, la Philosophical Society of Southern Africa (PSSA), a été marquée par des controverses concernant la représentation de la philosophie africaine. Comme l'a souligné Abraham Olivier, professeur de philosophie à l'Université de Fort Hare, dans sa conférence critique sur l'histoire du SAJP, malgré les prétentions de la revue à une large portée et à un statut officiel, ses contributions à la philosophie africaine ont été limitées et problématiques<ref>Global Phi, « A Critical History of the South African Journal of Philosophy », disponible sur https://www.uni-hildesheim.de/glophi/2025/05/13/a-critical-history-of-the-south-african-journal-of-philosophy-abraham-olivier/</ref>. Le SAJP a été fondé pendant l'apartheid, fortement dominé par des philosophes blancs sud-africains et anglais. Les philosophes noirs, comme Mabogo More, ont fait face au racisme systémique et à l'exclusion lors des conférences philosophiques. Malgré la chute de l'apartheid en 1994, de nombreux philosophes blancs ont continué à « rester en dehors de la politique », et la communauté philosophique est restée largement non transformée. Les tentatives d'intégrer la philosophie africaine dans la publication philosophique grand public ont été minimes et souvent symboliques. === Les revues internationales === Les philosophes ghanéens publient également dans un large éventail de revues philosophiques internationales de premier plan. Cette présence internationale témoigne de la reconnaissance de la qualité et de la pertinence de la philosophie ghanéenne dans les débats philosophiques mondiaux. ==== Revues de philosophie africaine ==== Outre les revues sud-africaines, les philosophes ghanéens publient dans d'autres revues spécialisées en philosophie africaine. ''Philosophia Africana'', publiée par Philosophy Documentation Center, est une revue internationale importante pour la philosophie africaine. ''African Identities'', publiée par Routledge, accueille également des contributions philosophiques. ''The Journal of African Cultural Studies'', publié par Taylor & Francis, publie des travaux interdisciplinaires incluant la philosophie. ==== Revues généralistes de philosophie ==== Les philosophes ghanéens publient régulièrement dans des revues philosophiques généralistes de premier plan. Le ''European Journal of Political Theory'', publié par SAGE Publications, a notamment publié l'article important de Martin Odei Ajei « Kwasi Wiredu's Consensual Democracy: Prospects for Practice in Africa » en 2016<ref>Ajei, Martin Odei, « Kwasi Wiredu's Consensual Democracy: Prospects for Practice in Africa », ''European Journal of Political Theory'', vol. 15, n° 4, 2016, p. 445-466</ref>. ''The Philosophical Forum'', publié par Wiley-Blackwell, a récemment publié un numéro spécial sur la démocratie consensuelle africaine édité par Richmond Kwesi, incluant son article « The Will to Consensus » (2024)<ref>Kwesi, Richmond, « The Will to Consensus », ''The Philosophical Forum'', vol. 55, n° 1, 2024, p. 45-62</ref>. ==== Revues de bioéthique et d'éthique de la santé ==== Dans le domaine de la bioéthique, les philosophes ghanéens, notamment Caesar Atuire, publient dans des revues prestigieuses telles que ''Public Health Ethics'' (Oxford Academic), ''BMJ Global Health'', ''The Hastings Center Report'', ''Developing World Bioethics'', et ''Transcultural Psychiatry''. L'article « Realizing Ubuntu in Global Health: An African Approach to Global Health Justice » de Nancy Jecker et Caesar Atuire, publié dans ''Public Health Ethics'' en 2022, constitue une contribution majeure à la bioéthique globale<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health: An African Approach to Global Health Justice », ''Public Health Ethics'', vol. 15, n° 3, 2022, p. 256-267</ref>. === Ouvrages collectifs et monographies === Au-delà des revues académiques, les philosophes ghanéens contribuent également à des ouvrages collectifs majeurs et publient des monographies influentes. ''The Oxford Handbook of Comparative Political Theory'' (2019) a publié le chapitre de Martin Odei Ajei « Toward a Tradition of Ghanaian Political Philosophy », offrant une visibilité importante à la philosophie politique ghanéenne dans un ouvrage de référence prestigieux<ref>Ajei, Martin Odei, « Toward a Tradition of Ghanaian Political Philosophy », dans Leigh K. Jenco, Murad Idris et Megan C. Thomas (dir.), ''The Oxford Handbook of Comparative Political Theory'', Oxford, Oxford University Press, 2019, p. 125-141</ref>. Les ouvrages classiques de Kwasi Wiredu, Kwame Gyekye et Kwame Anthony Appiah, publiés par des presses universitaires prestigieuses (Cambridge University Press, Oxford University Press, Temple University Press, W. W. Norton), continuent d'être largement lus et cités dans la littérature philosophique mondiale. Ces publications ont établi la philosophie ghanéenne comme une contribution majeure à la philosophie mondiale. Plus récemment, le volume ''Disentangling Consciencism: Essays on Kwame Nkrumah's Philosophy'', édité par Martin Odei Ajei et publié par Lexington Books en 2016, et le volume ''Bioethics in Africa: Theories and Praxis'', coédité par Caesar Atuire et publié par Vernon Press en 2019, témoignent de la vitalité continue de la production philosophique ghanéenne<ref>Ajei, Martin Odei (dir.), ''Disentangling Consciencism: Essays on Kwame Nkrumah's Philosophy'', Lanham, Lexington Books, 2016</ref><ref>Atuire, Caesar A. et al. (dir.), ''Bioethics in Africa: Theories and Praxis'', Vernon Press, 2019</ref>. === Défis et perspectives pour la publication philosophique ghanéenne === Malgré cette infrastructure éditoriale impressionnante, la publication philosophique ghanéenne fait face à plusieurs défis. L'un des principaux défis concerne la visibilité et l'indexation des revues africaines dans les bases de données internationales majeures. Bien que le LJH soit indexé dans le DOAJ et disponible sur AJOL et JSTOR, il n'est pas encore inclus dans certaines bases de données majeures comme Web of Science ou Scopus, ce qui peut limiter sa visibilité internationale. Un autre défi concerne le financement de la publication en libre accès. Bien que le LJH suive un modèle diamant sans frais pour les auteurs, ce modèle nécessite un financement institutionnel ou externe stable. Le soutien de la Carnegie Corporation de New York à travers le projet BANGA-Africa est crucial, mais la durabilité à long terme nécessite des sources de financement diversifiées. La question de la langue de publication constitue également un défi. Bien que l'anglais soit la langue dominante de la publication philosophique au Ghana (héritage colonial), cela peut limiter l'accessibilité de la recherche philosophique ghanéenne aux communautés non anglophones en Afrique et ailleurs. Le développement de la publication philosophique dans les langues ghanéennes pourrait enrichir la philosophie ghanéenne en permettant l'articulation de concepts philosophiques dans des cadres linguistiques autochtones. Enfin, la nécessité de renforcer les liens entre la recherche philosophique publiée et les politiques publiques reste un chantier ouvert. Comme l'a souligné Martin Odei Ajei, les perspectives philosophiques ghanéennes sur l'éducation, la gouvernance et d'autres questions importantes n'ont pas encore trouvé d'expression adéquate dans la formulation des politiques publiques<ref>Ajei, Martin Odei, « Educating Africans: Perspectives of Ghanaian Philosophers », op. cit.</ref>. Développer des plateformes de publication et de communication qui permettent un dialogue plus efficace entre philosophes et décideurs politiques pourrait accroître l'impact social de la philosophie ghanéenne. == Les événements académiques et commémoratifs == La philosophie ghanéenne se distingue non seulement par ses contributions théoriques, mais également par une vie académique dynamique marquée par des événements réguliers qui célèbrent son patrimoine intellectuel, honorent ses figures fondatrices et stimulent le débat philosophique contemporain. Ces événements témoignent de la vitalité de la communauté philosophique ghanéenne et de son engagement envers la transmission intergénérationnelle des savoirs. === La conférence annuelle Anton Wilhelm Amo === La conférence Anton Wilhelm Amo constitue l'un des événements académiques les plus prestigieux de la philosophie ghanéenne contemporaine. Introduite en 2021 par le Maria Sibylla Merian Institute for Advanced Studies in Africa (MIASA) à l'Université du Ghana, cette conférence annuelle honore Anton Wilhelm Amo, le philosophe africain du XVIIIe siècle originaire de l'actuel Ghana qui enseigna aux universités de Halle et de Jena en Allemagne<ref>MIASA, « Anton Wilhelm Amo Lecture, University of Ghana », disponible sur https://miasa.hypotheses.org/2317</ref>. La conférence sert l'un des objectifs clés de MIASA : contribuer à la décolonisation de la production de connaissances et à la justice épistémique. Pour les besoins de la conférence Anton Wilhelm Amo, MIASA collabore avec le département de philosophie et de classiques et l'Institute of African Studies de l'Université du Ghana<ref>MIASA, « Anton Wilhelm Amo Lecture, University of Ghana », op. cit.</ref>. En tant qu'événement majeur de l'Université du Ghana, la conférence se tient au Great Hall du campus de Legon et est ouverte par une performance du Ghana Dance Ensemble, établissant ainsi un lien symbolique entre l'excellence académique et le patrimoine culturel ghanéen. La première conférence Amo en 2021 a coïncidé avec le dévoilement de la plaque Anton Wilhelm Amo rénovée au département de philosophie et de classiques, qui avait été initialement offerte par l'Université de Halle dans les années 1970, l'alma mater d'Amo<ref>MIASA, « Anton Wilhelm Amo Lecture, University of Ghana », op. cit.</ref>. La conférence de 2021 a été accompagnée d'un atelier sur la vie d'Amo et son héritage intellectuel pour la philosophie africaine et les discours contemporains. ==== Les conférenciers et thèmes (2021-2024) ==== La série de conférences Anton Wilhelm Amo a accueilli certains des intellectuels africains les plus distingués de notre temps, chacun abordant des questions cruciales pour la décolonisation épistémique et la production de connaissances africaines. '''2021 : Le professeur J. Obi Oguejiofor''' (Université Nnamdi Azikiwe, Nigeria) a présenté « The Significance of Anton Wilhelm Amo in Contemporary African Philosophy », réfléchissant sur l'histoire de la vie d'Amo et la perception de sa philosophie en Afrique de l'Ouest, en particulier sur la question de savoir comment Amo a été influencé par la pensée africaine<ref>MIASA, « Anton Wilhelm Amo Lecture, University of Ghana », op. cit.</ref>. '''2022 : La professeure Sylvia Tamale''' (Université Makerere, Ouganda) a demandé dans sa conférence « Decolonising Knowledge Production in Africa » de repenser les pratiques de production de connaissances héritées sans critique, de contourner les gardiens intellectuels et de démocratiser l'espace épistémique<ref>MIASA, « Anton Wilhelm Amo Lecture, University of Ghana », op. cit.</ref>. La professeure Tamale a soutenu que la décolonisation de la production de connaissances nécessite une transformation profonde qui va au-delà de simples réformes curriculaires. '''2023 : Le professeur Felwine Sarr''' (Université Duke, États-Unis) a abordé la question de « Building African Ecologies of Knowledge »<ref>MIASA, « Anton Wilhelm Amo Lecture 2023: Building African Ecologies of Knowledge », disponible sur https://miasa.ug.edu.gh/event/amo-lecture-2023/</ref>. Le professeur Sarr, philosophe, économiste, écrivain et musicien sénégalais, a invité le public à apprécier la pluralité des connaissances qui vont au-delà d'une idée occidentale de ce qui est perçu comme connaissance ou non. Sarr, qui a été nommé par le magazine Time parmi les 100 personnes les plus influentes en 2021 avec Bénédicte Savoy après la publication de leur rapport sur « La restitution du patrimoine culturel africain » (2018), a appelé à reconnaître les multiples écologies de savoir qui existent en Afrique. La conférence complète est accessible en ligne et a été largement couverte par les médias ghanéens. '''2024 : Le professeur Toyin Falola''' (Université du Texas à Austin, États-Unis) a présenté « Ancestral Knowledge for Contemporary Transformation » le 15 octobre 2024<ref>MIASA, « Anton Wilhelm Amo Lecture 2024: Ancestral Knowledge for Contemporary Transformation », disponible sur https://miasa.ug.edu.gh/event/amo-lecture-2024/</ref><ref>Modern Ghana, « 2024 Anton Wilhelm Amo Lecture: "Don't throw away ancestral knowledge" », 15 octobre 2024, disponible sur https://www.modernghana.com/news/1349438/2024-anton-wilhelm-amo-lecture-dont-throw-away.html</ref>. Le professeur Falola, titulaire de plus de 20 doctorats honorifiques et président d'une conférence annuelle portant son nom (TOFAC - Toyin Falola Annual Conference on Africa and the African Diaspora), a passionnément appelé les jeunes africains à ne pas rejeter leur riche patrimoine culturel. « Les jeunes hommes et femmes qui sont ici, ne jetez pas cette connaissance [africaine] », a-t-il souligné, les encourageant à étudier la technologie de manière approfondie tout en trouvant des moyens de la fusionner avec la sagesse autochtone. Le professeur Falola a expliqué que les systèmes de connaissances traditionnelles africaines — en particulier la compréhension des plantes indigènes et de leurs utilisations — recèlent un immense potentiel pour relever les défis contemporains. « Utilisez la technologie comme un pont, puisez des ressources dans ce passé », a-t-il suggéré. Il a également abordé les dimensions éthiques de la connaissance et de la gouvernance, proposant que ces valeurs pourraient être essentielles pour réformer les systèmes corrompus et évaluer le leadership. « Nous les utiliserons pour réformer l'État corrompu. Nous les utiliserons pour évaluer le leadership », a-t-il affirmé. Dans ses remarques d'ouverture, la Dre Grace Diabah, directrice de MIASA Ghana, a souligné l'importance de la conférence Anton Wilhelm Amo pour souligner l'importance des voix africaines dans le discours intellectuel. « La vie d'Amo est un rappel de la longue histoire d'interconnexion ghanéo-allemande et une inspiration pour la production de connaissances », a déclaré la Dre Diabah. === Les conférences mémorielles Kwame Gyekye === En avril 2024, l'Université du Ghana a institué une nouvelle série de conférences mémorielles en l'honneur du professeur émérite Kwame Gyekye, l'un des philosophes africains les plus éminents de notre époque<ref>University of Ghana, « UG holds maiden edition of the Kwame Gyekye Memorial Lecture to celebrate philosopher », 18 avril 2024, disponible sur https://univers.ug.edu.gh/ug-holds-maiden-edition-of-the-kwame-gyekye-memorial-lecture-to-celebrate-philosopher/</ref><ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », 21 avril 2024, disponible sur https://old1.ug.edu.gh/news/late-emeritus-prof-kwame-gyekyes-intellectual-legacy-celebrated-maiden-memorial-lecture</ref>. Cette conférence mémorielle a été organisée par le département de philosophie et de classiques sous la direction du professeur Hasskei Mohammed Majeed (directeur du département), en collaboration avec la famille Gyekye. ==== La première conférence mémorielle Kwame Gyekye (2024) ==== La conférence inaugurale s'est tenue le 16 avril 2024 au Great Hall de l'Université du Ghana, marquant le cinquième anniversaire de la disparition du professeur Gyekye survenue le 13 avril 2019. L'événement était d'une importance nationale exceptionnelle, avec la présence de Son Excellence Nana Addo Dankwa Akufo-Addo, président de la République du Ghana, comme invité d'honneur spécial, et de Son Excellence John Agyekum Kufuor, ancien président du Ghana, comme invité d'honneur<ref>RGG News, « President Akufo-Addo at Maiden Kwame Gyekye Memorial Lectures », 16 avril 2024, disponible sur https://rggnews.com/president-akufo-addo-at-maiden-kwame-gyekye-memorial-lectures/</ref>. Le président Akufo-Addo a salué l'héritage intellectuel du professeur émérite, le décrivant comme une figure imposante de la philosophie africaine. « Le professeur Gyekye n'était pas seulement un philosophe ; il était un visionnaire dont les idées transcendaient les frontières et trouvaient un écho auprès des personnes de tous les horizons », a remarqué le président Akufo-Addo. Il a reconnu l'impact profond des œuvres du professeur Gyekye sur l'érudition et le discours. « Au-delà de ses efforts académiques, le professeur Gyekye est apparu comme un ardent défenseur de l'unité et du développement africains, défendant des solutions africaines aux problèmes africains. Son héritage, encapsulé dans des œuvres telles que "African Cultural Values and Introduction", continue d'inspirer l'espoir d'un avenir meilleur pour l'Afrique », a divulgué le président dans ses remarques<ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », op. cit.</ref>. La vice-chancelière, la professeure Nana Aba Appiah Amfo, a pour sa part loué le professeur Gyekye et son rôle central dans la réduction de l'écart entre la philosophie occidentale et la pensée africaine. La professeure Amfo a salué l'engagement du professeur émérite Gyekye à contextualiser le discours philosophique dans le riche contexte de la culture et de la tradition africaines, notant avec fierté l'association de l'Université du Ghana avec le distingué érudit. Elle a exprimé l'espoir que « l'institution de la conférence mémorielle Kwame Gyekye sur la citoyenneté enflammerait un sens du devoir civique, en particulier parmi la jeune génération, et raviverait l'esprit de patriotisme pour l'avancement et la prospérité de la nation »<ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », op. cit.</ref>. Le professeur Martin Odei Ajei, professeur associé de philosophie au département de philosophie et de classiques de l'Université du Ghana et membre de la Ghana Academy of Arts and Sciences, a prononcé une conférence mémorielle perspicace intitulée « The Forgetfulness of Citizenship », se concentrant sur les conditions nuancées régissant la reconnaissance de la citoyenneté dans les cadres constitutionnels et juridiques du Ghana. S'appuyant sur un riche éventail de cas et d'aperçus tirés des œuvres séminales du professeur Kwame Gyekye, le conférencier mémoriel a exploré les principes humanistes de laïcité, d'égalité et d'équité, qui ont historiquement influencé le paysage politique du Ghana et façonné les identités sociales et culturelles<ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », op. cit.</ref>. Au cœur de son argument se trouvait l'affirmation que les concepts de citoyenneté communautarienne modérée du professeur Gyekye revêtent une pertinence profonde pour favoriser des identités nationales propices à la stabilité sociale et à un engagement collectif envers le bien commun. « En plaidant pour des modèles de citoyenneté fondés sur des principes d'appartenance communale et de responsabilité partagée, les idées du professeur Gyekye offrent des perspectives précieuses pour nourrir des sociétés cohésives où les individus trouvent un sentiment d'appartenance et contribuent au bien-être de la nation dans son ensemble », a intimé le professeur Ajei. À travers son exploration savante, le professeur Ajei a souligné l'importance d'intégrer les perspectives du professeur Gyekye dans le discours contemporain sur la citoyenneté et l'identité nationale, soulignant le potentiel de promouvoir l'inclusivité, la cohésion sociale et un sens collectif du but<ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », op. cit.</ref>. Son Honneur le juge Emmanuel Yonny Kulendi, juge de la Cour suprême, qui présidait l'événement, a rendu un hommage éclatant au professeur Gyekye pour ses efforts délibérés pour reconnecter les gens avec leur héritage culturel. « Sa croyance en l'eschew de l'individualisme en faveur de la chérison du communautarisme devrait servir de principe directeur pour favoriser une citoyenneté plus responsable », a remarqué le juge Kulendi, soulignant l'influence durable de Gyekye sur les valeurs et normes sociétales<ref>University of Ghana, « Late Emeritus Prof. Kwame Gyekye's Intellectual Legacy Celebrated at Maiden Memorial Lecture », op. cit.</ref>. En prononçant le vote de remerciements au nom de la famille, la Dre Maame Adwoa Gyekye-Gyandoh, fille du professeur émérite Kwame Gyekye, a exprimé son appréciation à l'équipe organisatrice ainsi qu'à tous les invités distingués qui ont honoré l'occasion<ref>University of Ghana, « UG holds maiden edition of the Kwame Gyekye Memorial Lecture to celebrate philosopher », op. cit.</ref>. Le professeur Hasskei Majeed, directeur du département de philosophie et de classiques, a partagé avec l'audience les histoires de transformation évidentes des étudiants et des conférenciers enseignés par l'éminent défunt. « Nous célébrons le professeur émérite Gyekye en raison de son immense contribution à la croissance du département et à la philosophie Akan. Gyekye était un philosophe africain pionnier qui, pendant quatre décennies, a enseigné la philosophie africaine et des cours connexes aux étudiants du département », a déclaré le professeur Majeed<ref>University of Ghana, « UG holds maiden edition of the Kwame Gyekye Memorial Lecture to celebrate philosopher », op. cit.</ref>. La conférence mémorielle Kwame Gyekye a offert une opportunité pour la famille du philosophe défunt, la communauté universitaire, les collègues, les étudiants et les admirateurs de réfléchir sur les contributions du professeur Gyekye à l'académie, en particulier dans les domaines de la pensée, de l'éthique et de l'érudition africaines. Dans le but de préserver la mémoire et d'assurer que l'héritage intellectuel du philosophe défunt perdure, inspirant les générations futures, la conférence mémorielle deviendra un événement annuel dans l'espoir de susciter un intérêt renouvelé pour son œuvre et de favoriser un dialogue continu sur ses contributions à la philosophie et aux études africaines<ref>University of Ghana, « UG holds maiden edition of the Kwame Gyekye Memorial Lecture to celebrate philosopher », op. cit.</ref>. ==== La deuxième conférence mémorielle Kwame Gyekye (2025) ==== La deuxième conférence mémorielle Kwame Gyekye s'est tenue le 30 avril 2025 au Great Hall de l'Université du Ghana, avec comme thème « Coloniality, Citizenship, and Galamsey »<ref>University of Ghana, « The 2nd Kwame Gyekye Memorial Lecture - 2025 », 30 avril 2025, disponible sur https://www.youtube.com/watch?v=Wy9Y_L7JbwU</ref>. Cette conférence a abordé des questions cruciales pour le Ghana contemporain, notamment la question de l'extraction minière illégale (galamsey) et ses implications pour la citoyenneté et la gouvernance dans un contexte postcolonial. === Les conférences et colloques académiques === Au-delà des événements commémoratifs annuels, la philosophie ghanéenne organise régulièrement des conférences et colloques académiques qui stimulent le débat intellectuel et favorisent les échanges entre chercheurs de différentes générations et nationalités. ==== La première conférence internationale des étudiants diplômés (2025) ==== En décembre 2025 se tiendra la première conférence internationale des étudiants diplômés sur les classiques et la philosophie, organisée par le département de philosophie et de classiques de l'Université du Ghana en collaboration avec la Classical Association of Ghana<ref>PhilEvents, « 1st International Graduate Conference (Classical Association of Ghana) », disponible sur https://philevents.org/event/show/135601</ref><ref>PhilEvents, « CFP: 1st International Graduate Conference (Classical Association of Ghana) », disponible sur https://philevents.org/event/show/135605</ref>. Cette conférence inaugurale, prévue les 16 et 17 décembre 2025, bénéficie du généreux soutien de la Princeton Africa World Initiative de l'Université de Princeton et de la Faculté des classiques de l'Université de Cambridge. La conférence explorera le concept de « vice » et ses diverses manifestations et effets. Le vice est traditionnellement conçu comme ce qui est déficient ou ne parvient pas à atteindre le bien. Il se manifeste de plusieurs manières : le social (l'injustice épistémique : lorsqu'un auditeur accorde une crédibilité diminuée à un locuteur non pas en fonction du mérite du discours du locuteur mais en raison de la race, du genre, de l'identité religieuse ou de toute autre raison) ; le politique (la kakistocratie : mauvaise gouvernance, corruption politique ; kakonomia, mauvaise constitution) ; le moral (libertinage, paresse, avidité dus à la force compétitive des désirs pleonectiques sur la continence ou la modération)<ref>PhilEvents, « 1st International Graduate Conference (Classical Association of Ghana) », op. cit.</ref>. Les domaines thématiques qui seront explorés incluent, sans s'y limiter, les suivants : la nature et la métaphysique du vice, l'agence, le libre arbitre et le vice, la corruption politique, l'injustice épistémique, les mauvaises lois et la gouvernance, la phénoménologie de la haine, Thucydide sur l'origine de la stasis et du polemos, l'hubris et l'apothéose, la psychologie du mal, la tragédie grecque et le vice (par exemple, l'infanticide, le matricide, l'uxoricide, le conjuxide, etc.), Dieu, les humains et les limites de la piété et de la raison (par exemple, le destin d'Œdipe, Créon et Antigone sur la prise de décision correcte), l'origine du mal, et le concept africain du mal<ref>PhilEvents, « 1st International Graduate Conference (Classical Association of Ghana) », op. cit.</ref>. Des bourses de voyage (depuis les capitales principales, par exemple Johannesburg, vers Accra) seront disponibles pour les candidats retenus des universités d'Afrique. Chaque présentateur se verra attribuer 20 minutes pour la présentation et 10 minutes pour les questions-réponses. Chaque article se verra attribuer un répondant, un chercheur senior dans le domaine thématique sélectionné. Les organisateurs de la conférence sont Stephen Peprah (PhD) (Université du Ghana et Université de Toronto) et Michael Okyere Asante (Université de Cambridge et UESD, Somanya)<ref>PhilEvents, « CFP: 1st International Graduate Conference (Classical Association of Ghana) », op. cit.</ref>. Cette conférence à venir marque une étape importante dans le développement de la philosophie ghanéenne en créant une plateforme spécifiquement dédiée aux jeunes chercheurs et en renforçant les liens avec des institutions académiques prestigieuses au niveau mondial. Le soutien de Princeton et Cambridge témoigne de la reconnaissance internationale de la qualité de la philosophie ghanéenne et de l'importance d'investir dans la prochaine génération de philosophes africains. === La cérémonie d'hommage au professeur Kwame Gyekye (2007) === Bien avant l'institution de la conférence mémorielle annuelle, le département de philosophie et de classiques avait déjà rendu un hommage majeur au professeur Kwame Gyekye de son vivant. En 2007, le département a organisé une cérémonie en l'honneur du professeur Gyekye pour célébrer le 40e anniversaire de son doctorat de Harvard et ses 40 années de service au département et à l'Université du Ghana<ref>GhanaDot, « Legon Philosophy Department honours Kwame Gyekye », disponible sur http://www.ghanadot.com/personalities.profkyekye.061509.html</ref>. La citation soulignait que Gyekye n'était pas seulement un érudit et philosophe, mais également un enseignant, ami, mari, père et grand-père, et saluait ses contributions exceptionnelles à l'étude de la philosophie qui ont tracé un chemin pour les générations futures d'étudiants et d'universitaires. Au cours de ses quatre décennies de service à l'université, Gyekye a occupé plusieurs postes administratifs importants, notamment Vice Master de l'Akuafo Hall, directeur du département de philosophie, doyen de la Faculté des arts, doyen de l'École de recherche et des études supérieures, ainsi que président de plusieurs conseils d'administration<ref>GhanaDot, « Legon Philosophy Department honours Kwame Gyekye », op. cit.</ref>. Cette cérémonie de 2007 a établi un précédent important pour la reconnaissance publique des contributions des philosophes ghanéens et a anticipé la création ultérieure de la conférence mémorielle annuelle. === L'importance des événements académiques et commémoratifs === Ces événements académiques et commémoratifs jouent un rôle crucial dans la vie intellectuelle de la philosophie ghanéenne. Ils remplissent plusieurs fonctions essentielles : '''Transmission intergénérationnelle''' : Les conférences commémoratives assurent la transmission de l'héritage intellectuel des figures fondatrices aux nouvelles générations de philosophes, créant une continuité dans la tradition philosophique ghanéenne. '''Légitimation institutionnelle''' : La présence de hauts dignitaires de l'État, comme le président de la République du Ghana à la conférence Gyekye, confère une reconnaissance politique et sociale à la philosophie et affirme son importance pour la nation. '''Dialogue intergénérationnel''' : Ces événements créent des espaces où étudiants, jeunes chercheurs et philosophes établis peuvent interagir, favorisant ainsi le renouvellement et la continuité de la tradition philosophique. '''Visibilité internationale''' : Le soutien d'institutions prestigieuses comme Princeton, Cambridge, et Duke, ainsi que la participation de conférenciers internationaux de renom, renforcent la visibilité et la légitimité internationales de la philosophie ghanéenne. '''Engagement public''' : En se tenant dans des lieux prestigieux comme le Great Hall de l'Université du Ghana et en étant ouverts au public (avec participation virtuelle), ces événements permettent à la philosophie de toucher un public plus large que la seule communauté académique. '''Décolonisation épistémique''' : Les thèmes abordés — décolonisation de la production de connaissances, justice épistémique, écologies de savoir africaines, connaissance ancestrale — placent la question de la décolonisation au cœur de l'agenda philosophique ghanéen. '''Célébration culturelle''' : L'ouverture de ces événements par des performances du Ghana Dance Ensemble crée un lien symbolique entre excellence académique et patrimoine culturel, affirmant l'enracinement de la philosophie dans la culture ghanéenne. Ces événements témoignent ainsi de la maturité et de la vitalité de la philosophie ghanéenne, capable à la fois d'honorer son passé, de stimuler son présent et de préparer son avenir. == Les thèmes centraux de la philosophie ghanéenne récente == La philosophie ghanéenne contemporaine se distingue par plusieurs thèmes centraux qui structurent ses contributions aux débats philosophiques africains et mondiaux. Ces thèmes reflètent à la fois un enracinement dans les préoccupations spécifiquement africaines et une ouverture aux questions philosophiques universelles. Ils témoignent également d'une tradition intellectuelle mature, capable de développer des concepts originaux et de proposer des alternatives théoriques aux paradigmes dominants de la philosophie occidentale. === La décolonisation conceptuelle et épistémique === Le projet de décolonisation conceptuelle inauguré par Kwasi Wiredu demeure un axe central et structurant de la philosophie ghanéenne contemporaine. Ce projet constitue l'une des contributions les plus originales et les plus influentes de la philosophie africaine à la pensée mondiale. ==== Les fondements de la décolonisation conceptuelle ==== Wiredu a introduit pour la première fois le concept de « décolonisation conceptuelle » lors d'une conférence de l'UNESCO en juin 1980 sur « L'enseignement et la recherche en philosophie en Afrique »<ref>Wiredu, Kwasi, « The Need for Conceptual Decolonization in African Philosophy », disponible sur http://www.galerie-inter.de/kimmerle/Kwasi.htm</ref>. Par décolonisation conceptuelle, Wiredu entend deux choses complémentaires. Du côté négatif, il s'agit d'éviter ou d'inverser, par une prise de conscience conceptuelle critique, l'assimilation non examinée dans la pensée des philosophes africains contemporains des cadres conceptuels ancrés dans les traditions philosophiques étrangères qui ont eu un impact sur la vie et la pensée africaines. Du côté positif, il s'agit d'exploiter autant que possible les ressources des schèmes conceptuels indigènes africains dans les méditations philosophiques, même sur les problèmes les plus techniques de la philosophie contemporaine<ref>Wiredu, Kwasi, « The Need for Conceptual Decolonization in African Philosophy », op. cit.</ref>. La nécessité de la décolonisation conceptuelle a été imposée par la superimposition historique de catégories de pensée étrangères sur les systèmes de pensée africains à travers le colonialisme. Cette superimposition s'est produite principalement par trois voies : la langue, la religion et la politique<ref>Wiredu, Kwasi, « Conceptual Decolonization as an Imperative in Contemporary African Philosophy: Some Personal Reflections », ''Rue Descartes'', vol. 36, n° 2, 2002, p. 53-64</ref>. Le fait que les philosophes africains mènent leurs réflexions philosophiques dans des langues coloniales (anglais, français, portugais) plutôt que dans leurs langues maternelles crée des problèmes conceptuels significatifs, car les cadres conceptuels sont souvent enchâssés dans les structures linguistiques. Wiredu soutient que la philosophie africaine doit dépasser le stade de la simple collecte de proverbes et de sagesses ancestrales pour s'engager dans les domaines formalisés de l'enquête philosophique, tels que la logique symbolique, la philosophie des mathématiques et des sciences naturelles, ou encore la philosophie morale, politique et sociale<ref>Hallen, Barry, ''Reading Wiredu'', Bloomington, Indiana University Press, 2021, p. 15-32</ref>. Cependant, cet engagement ne doit pas se faire par une simple imitation des approches occidentales, mais en mobilisant les ressources conceptuelles des traditions africaines. ==== L'exemple paradigmatique : la conception Akan de l'esprit ==== Dans son essai « Conceptual Decolonization as an Imperative in Contemporary African Philosophy », Wiredu déploie une stratégie particulière pour démontrer que la conception Akan de l'esprit est supérieure à la conception cartésienne dualiste<ref>Internet Encyclopedia of Philosophy, « Kwasi Wiredu (1931—2022) », disponible sur https://iep.utm.edu/wiredu/</ref>. Il soutient que la conception Akan de la personne, qui ne sépare pas radicalement l'esprit et le corps comme le fait le dualisme cartésien, offre une compréhension plus adéquate de la nature humaine. Dans la pensée Akan, la personne est conçue comme une unité complexe plutôt que comme une substance pensante (res cogitans) distincte d'une substance étendue (res extensa). Cette démonstration a suscité des débats importants. Certains critiques, comme Olufémi Táíwò, ont objecté que Wiredu simplifie parfois les concepts non-indigènes qu'il soumet à l'examen critique<ref>Oxford Academic, « Conceptual Decolonization, Conceptual Justice, and Religious Concepts », ''Mind'', vol. 134, n° 533, octobre 2024, p. 60-89</ref>. Néanmoins, même les critiques reconnaissent que le projet de décolonisation conceptuelle de Wiredu peut encourager l'élargissement conceptuel et offre une perspective précieuse sur les limites des cadres philosophiques occidentaux. ==== Les critiques et développements du projet ==== Le projet de décolonisation conceptuelle de Wiredu a fait l'objet de nombreuses analyses critiques qui ont contribué à son raffinement. Dans une étude récente, des chercheurs ont tenté de montrer que le projet de décolonisation conceptuelle de la philosophie africaine par recours à la théorisation dans les vernaculaires africains est problématique<ref>Philosophia Africana, « A Critique of Wiredu's Project of Conceptual Decolonization of African Philosophy », vol. 22, n° 1, 2023, p. 61-88</ref>. Ils démontrent que la tentative de Wiredu de montrer la supériorité de la conception Akan de l'esprit est infructueuse et que son projet de décolonisation conceptuelle échoue dans cette instance particulière. Néanmoins, ils concluent que le projet de décolonisation conceptuelle de Wiredu montre toujours des promesses, même à la lumière de leurs critiques. D'autres chercheurs ont examiné l'impact de la mondialisation sur la décolonisation conceptuelle de Wiredu<ref>Mediterranean Journal of Social Sciences, « Assessing the Impacts of Globalization on Kwasi Wiredu's Conceptual Decolonization in African Philosophy », vol. 11, n° 5, septembre 2020</ref>. Ils observent que la décolonisation conceptuelle de Wiredu est distinctement opposée aux principes et tenets de la mondialisation en tant que concept socio-politique inspiré par l'expansion économique et culturelle occidentale. Cette tension entre décolonisation conceptuelle et mondialisation soulève des questions importantes sur la viabilité du projet de Wiredu dans un monde de plus en plus interconnecté. ==== La décolonisation épistémique dans l'enseignement supérieur ==== Le projet de décolonisation conceptuelle de Wiredu a inspiré des travaux plus récents sur la décolonisation épistémique dans l'enseignement supérieur africain. Husein Inusah, de l'Université de Cape Coast, a soutenu que la décolonisation épistémique doit aller au-delà des réformes curriculaires et pédagogiques actuelles pour s'attaquer aux structures profondes de production et de validation des connaissances<ref>Inusah, Husein, « Epistemic Decolonisation in African Higher Education: Beyond Current Curricular and Pedagogical Reformation », ''South African Journal of Higher Education'', vol. 37, n° 2, 2023, p. 87-105</ref>. La dynamique de la décolonisation épistémique au XXIe siècle s'inscrit dans une longue histoire de résistance à l'exil ontologique et épistémique des peuples colonisés<ref>Strategic Review for Southern Africa, « The Dynamics of Epistemological Decolonisation in the 21st Century: Towards Epistemic Freedom », vol. 42, n° 2, décembre 2020</ref>. La connexion entre la « ligne de couleur » et la « ligne épistémique » réside dans le déni raciste de l'humanité de ceux qui sont devenus les cibles de l'esclavage et de la colonisation. Le déni d'humanité disqualifie automatiquement de la vertu épistémique. Cette étude explore comment l'Afrique en particulier et le reste du Sud global en général sont devenus victimes de génocides, d'épistémicides, de linguicides et de culturecides. ==== L'impact sur la philosophie de la religion ==== La décolonisation conceptuelle a également eu un impact significatif sur la philosophie africaine de la religion. Une évaluation des contributions de Wiredu à la philosophie africaine de la religion montre que les questions de décolonisation conceptuelle, de reconstructionnisme culturel et de la nature des philosophies africaines sous-tendent son travail<ref>International Journal of Current Research in the Humanities, « An Assessment of Kwasi Wiredu's Contributions to African Philosophy of Religion », vol. 9, n° 1, avril 2024</ref>. Pour les philosophes contemporains, il convient d'adopter le cadre analytique de Wiredu, mais des approches culturellement ancrées et réalistes doivent être adoptées dans la pratique de la philosophie africaine. Les diversités des cultures et traditions africaines nécessitent également une approche pluraliste de diverses parties de l'Afrique. === La démocratie consensuelle et la philosophie politique === La question de la démocratie en Afrique constitue un thème majeur de la philosophie ghanéenne récente. Le débat porte notamment sur la nature de la démocratie africaine et sur la pertinence du consensus par opposition au principe majoritaire. ==== Les fondements de la démocratie consensuelle ==== Dans son essai influent « Democracy and Consensus in African Traditional Politics: A Plea for a Non-Party Polity » (1996), Wiredu propose l'adoption de la démocratie consensuelle comme alternative à la démocratie libérale majoritaire pratiquée dans la plupart des pays africains<ref>Wiredu, Kwasi, « Democracy and Consensus in African Traditional Politics: A Plea for a Non-Party Polity », dans Emmanuel Eze (dir.), ''Postcolonial African Philosophy'', Oxford, Blackwell, 1997, p. 303-312</ref>. Wiredu soutient que dans les sociétés africaines traditionnelles, qu'elles soient centralisées avec un roi ou un chef, ou décentralisées avec une structure gouvernementale formelle limitée, le fonctionnement reposait sur le consensus plutôt que sur le vote majoritaire. La démocratie consensuelle de Wiredu est un système démocratique indigène sans parti enraciné dans les conceptions humanistes et communautariennes traditionnelles africaines de l'individu et de la communauté, dans lequel les décisions politiques sont caractéristiquement atteintes par consensus. Les éléments centraux de la démocratie consensuelle de Wiredu, comme l'observe Gyekye, sont la gouvernance inclusive, une pluralité de participation et la délibération publique<ref>University of Cape Coast, « A Critical Study of Kwesi Wiredu's Consensual Democracy », thèse de D.K. Ahiaveh, 2021</ref>. ==== Les arguments en faveur de la démocratie consensuelle ==== Un défi politique auquel sont confrontées les démocraties constitutionnelles en Afrique est le manque de représentation et de participation adéquates des citoyens dans les processus et institutions démocratiques. Ce défi se manifeste dans l'attribution du pouvoir uniquement à un groupe sectionnel — le parti majoritaire — à l'exclusion des autres, comme en témoignent les systèmes démocratiques libéraux largement pratiqués sur le continent<ref>Ajei, Martin Odei, « Kwasi Wiredu's Consensual Democracy: Prospects for Practice in Africa », ''European Journal of Political Theory'', vol. 15, n° 4, 2016, p. 445-466</ref>. Wiredu propose comme solution à ces défis l'adoption de la démocratie consensuelle. Il soutient que la démocratie majoritaire a échoué à prendre en compte les intérêts des minorités dans le processus de prise de décision. Il considère la démocratie consensuelle comme un substitut viable et approprié à la démocratie majoritaire. Il estime que les droits et les intérêts des minorités qui ne sont pas pris en charge dans la démocratie majoritaire ne peuvent l'être que dans le cadre d'un processus consensuel<ref>Nigeria Journal of Philosophy, « Kwasi Wiredu's Consensual Democracy: Towards a Path of Realization in the Majoritarian Hemisphere », Julius Adekunle Fasina</ref>. Les arguments en faveur de la démocratie consensuelle incluent : (1) l'encouragement au dialogue continu et à l'inclusivité ; (2) la provision de solutions à long terme aux questions sociétales saillantes ; (3) la participation légitime au processus de prise de décision ; (4) la réduction de la dominance majoritaire ; (5) l'efficacité dans la résolution des conflits et la prévention des impasses ; (6) la promotion d'un environnement politique plus inclusif, stable et coopératif, conduisant à des décisions largement soutenues et durables<ref>Nigeria Journal of Philosophy, « Kwasi Wiredu's Consensual Democracy », op. cit.</ref>. ==== Les critiques et modifications proposées ==== Martin Odei Ajei a présenté une exposition critique de la démocratie consensuelle de Wiredu et l'a défendue contre la démocratie libérale d'une part, et contre les critiques qui lui sont adressées d'autre part<ref>Ajei, Martin Odei, « Kwasi Wiredu's Consensual Democracy », op. cit.</ref>. Ajei offre également quelques modifications à la théorie de Wiredu dans le but de la rendre plus adaptée à la pratique en Afrique. Il argumente que l'approche est appropriée pour l'Afrique et rejette l'idée d'un gouvernement majoritaire, tout comme Wiredu. Ajei et Wiredu soutiennent tous deux que la démocratie multipartite a entraîné la violence en Afrique et a donné un pouvoir indu au parti majoritaire. D'autres défenseurs importants de la pensée de Wiredu sur la démocratie consensuelle incluent Kwame Gyekye (1997), Edward Wamala (2004), Joe Teffo (2004), Joseph Omoregbe (2010), et Barry Hallen (2020). Dans son ouvrage intitulé « Reconsidering the Case for Consensual Governance in Africa » (2019), Hallen n'a pas seulement argumenté en faveur de la démocratie consensuelle, il a également appelé à une revisite et un retour qui devraient être pris au sérieux<ref>Nigeria Journal of Philosophy, « Kwasi Wiredu's Consensual Democracy », op. cit.</ref>. Gyekye a mené une étude complète sur la faisabilité de la démocratie consensuelle dans l'Afrique contemporaine. Il a affirmé que la croissance de la société postcoloniale a été influencée à la fois par les civilisations précoloniales et occidentales. Il soutient que l'Afrique moderne est plus complexe et diversifiée que l'Afrique précoloniale. Selon lui, les trois piliers principaux de la démocratie consensuelle de Wiredu — gouvernance inclusive, pluralité de participation et délibération publique — peuvent être adaptés au contexte africain contemporain malgré sa complexité accrue. ==== Les perspectives contemporaines ==== Des travaux récents continuent d'explorer les limites et les défenses de la démocratie consensuelle. Thaddeus Metz a publié en 2025 un article intitulé « The Defence and Limits of Consensual Democracy » qui examine de manière critique les arguments en faveur et contre la démocratie consensuelle dans le contexte africain contemporain<ref>Taylor & Francis, « The Defence and Limits of Consensual Democracy », ''European Journal of Political Theory'', 16 mai 2025</ref>. La question centrale demeure : comment actualiser la démocratie consensuelle au milieu des complexités, de la diversité et de la pluralité des sociétés africaines contemporaines ? Plusieurs chercheurs ont proposé un modèle éclectique ou hybride qui incorporerait les aspects positifs de la démocratie consensuelle dans le cadre de la démocratie majoritaire. Ce modèle encouragerait les changements progressifs et les compromis par le dialogue ouvert et la négociation, similaire au modèle de référendum que Fayemi (2020) a mis en avant. Les lacunes ou mauvais attributs de la démocratie majoritaire dans l'Afrique postcoloniale peuvent facilement être éliminés par l'infusion des aspects positifs de la démocratie consensuelle<ref>Nigeria Journal of Philosophy, « Kwasi Wiredu's Consensual Democracy », op. cit.</ref>. === L'Ubuntu, la solidarité et la bioéthique africaine === L'éthique de l'Ubuntu est devenue un thème majeur de la philosophie ghanéenne contemporaine, particulièrement dans le domaine de la bioéthique et de l'éthique de la santé mondiale. Cette application de concepts philosophiques africains à des problèmes contemporains globaux démontre la pertinence et la viabilité de la philosophie africaine pour les défis du XXIe siècle. ==== Les fondements philosophiques de l'Ubuntu ==== L'Ubuntu, bien qu'il n'ait pas d'équivalent anglais direct, est souvent traduit par « humanité » ou « dignité humaine » et englobe des dimensions à la fois ontologiques et normatives<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health: An African Approach to Global Health Justice », ''Public Health Ethics'', vol. 15, n° 3, novembre 2022, p. 256-267</ref>. La dimension ontologique est souvent exprimée par des dictons concis, tels que « une personne est une personne à travers d'autres personnes » et « je suis parce que nous sommes ». Une façon de comprendre cela est de dire que les êtres humains sont interdépendants et ont besoin les uns des autres, comme l'exprime la maxime Akan « un être humain a besoin d'aide ». Selon cette ontologie, la dépendance humaine n'est pas apparente seulement pendant la maladie et l'infirmité, mais existe comme un « résidu inéliminable » de l'humanité, reflétant des faits existentiels de l'existence humaine, tels que l'incarnation corporelle, qui rend les personnes susceptibles de subir des préjudices. Selon Wiredu, « les êtres humains... à tout moment, d'une manière ou d'une autre, directement ou indirectement, ont besoin de l'aide de leur genre »<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health », op. cit.</ref>. Un principe de base de l'éthique Ubuntu est le caractère donné de la vie communale. L'Ubuntu englobe également une composante normative. La composante normative soutient que l'interdépendance humaine nous enjoint de vivre une vie avec les autres qui soit harmonieuse et qui exprime une préoccupation et un soin mutuels. Le dicton africain « un être humain a besoin d'aide » ne transmet pas seulement un fait, mais prescrit également une conduite et un caractère. Décrivant l'aspect éthique de l'Ubuntu, Desmond Tutu déclare : « Une personne avec Ubuntu est ouverte et disponible pour les autres, affirmant les autres, ne se sent pas menacée par le fait que d'autres soient capables et bons, car elle a une assurance de soi appropriée qui vient de la connaissance qu'elle appartient à un ensemble plus grand et est diminuée lorsque d'autres sont humiliés ou diminués, lorsque d'autres sont torturés ou opprimés »<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health », op. cit.</ref>. ==== L'application de l'Ubuntu à la santé mondiale ==== Caesar Atuire, en collaboration avec Nancy Jecker de l'Université de Washington, a développé une approche africaine de la justice en santé mondiale basée sur les principes de l'Ubuntu<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health », op. cit.</ref>. La pandémie de COVID-19 a mis en évidence la question : « Que nous devons-nous les uns aux autres en tant que membres d'une communauté mondiale pendant une crise sanitaire mondiale ? » En tandem, elle a soulevé des préoccupations sous-jacentes sur la façon dont nous devrions nous préparer à la prochaine épidémie de maladie infectieuse et ce que nous devons aux personnes dans d'autres pays en temps normal. Alors que la littérature bioéthique dominante aborde ces questions en s'appuyant sur des valeurs et des concepts proéminents dans le Nord global, l'article de Jecker et Atuire articule des réponses proéminentes en Afrique subsaharienne. L'article introduit d'abord un « village de santé mondiale » figuratif pour orienter les lecteurs vers la pensée traditionnelle africaine. Ensuite, il considère les exigences éthiques pour gouverner un village de santé mondiale, en s'appuyant sur l'éthique de l'Ubuntu pour formuler des rendus africains de la solidarité, de la justice relationnelle et de la suffisance<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health », op. cit.</ref>. Le concept de « village de santé mondiale » s'inspire des peuples Builsa du Ghana, qui fournissent une façon de conceptualiser les devoirs et les droits que les êtres humains interconnectés ont les uns envers les autres. La section finale de l'article utilise ces valeurs pour critiquer les approches actuelles, y compris COVAX, le pilier vaccins de l'accélérateur Access to COVID-19 Tools (ACT), et un traité international sur les pandémies proposé. Il propose une voie à suivre qui réalise mieux l'Ubuntu dans la santé mondiale<ref>Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health », op. cit.</ref>. ==== L'Ubuntu dans la recherche en génomique clinique ==== Moodley et Beyer (2019) ont également appliqué l'Ubuntu pour aborder les préoccupations éthiques et sociales dans la recherche en génomique clinique. Ils ont développé un modèle basé sur la philosophie Ubuntu pour promouvoir un engagement communautaire efficace et éthiquement sain dans la recherche de biobanques, en se concentrant sur la valeur de la solidarité<ref>Institute for Ethics and AI, Technical University of Munich, « Ubuntu Ethics in AI for Healthcare: Enabling Equitable Care », février 2023</ref>. Ils ont souligné la complexité de l'obtention du consentement éclairé dans la biobanque génomique et ont soutenu qu'une approche basée sur l'Ubuntu de l'engagement communautaire améliorerait le processus de consentement. Dans le contexte de la divulgation d'informations sur le VIH/SIDA, Ewuoso (2020) a appliqué l'éthique Ubuntu pour aborder les questions éthiques qui découlent du « conflit entre » le droit à la confidentialité et le devoir de divulguer. L'éthique Ubuntu a également été appliquée aux tests de routine universels du VIH en Zambie, explorant les différences entre une bioéthique basée sur l'Ubuntu et les principes bioéthiques internationaux<ref>Journal of Medical Ethics, « International Bioethics, Ubuntu and HIV Testing in Sub-Saharan Africa », 2025</ref>. ==== Les limites et critiques de l'Ubuntu ==== Bien que l'Ubuntu soit devenu un concept central dans la bioéthique africaine, certains chercheurs ont appelé à une approche plus nuancée. Jaco de Vries (2024) a soutenu qu'en limitant notre regard en bioéthique à penser à l'Ubuntu (et aux termes analogues) comme le seul concept qui définit l'intellectualisme africain, nous risquons de simplifier excessivement la riche diversité de la pensée éthique africaine<ref>Wellcome Open Research, « Incompleteness, Conviviality and the Limits of Ubuntu », vol. 9, 2024</ref>. Il appelle à centrer l'Afrique comme contexte et moteur de l'éthique de la santé mondiale au-delà de l'Ubuntu. Néanmoins, l'Ubuntu reste un concept puissant pour articuler une approche africaine de problèmes globaux. Son emphase sur l'interdépendance, la solidarité et la justice relationnelle offre une alternative importante aux approches individualistes qui dominent la bioéthique occidentale. === La personne, la communauté et le communautarisme modéré === Le débat sur la nature de la personne et son rapport à la communauté dans la pensée africaine reste un thème central de la philosophie ghanéenne, inauguré par la controverse entre Kwame Gyekye et Ifeanyi Menkiti. ==== Le débat Gyekye-Menkiti ==== Le débat porte sur la question de savoir si, dans la pensée africaine, la communauté confère la personnalité à l'individu ou si l'individu possède une valeur intrinsèque indépendante de la communauté. Ifeanyi Menkiti soutenait que la communauté confère la personnalité à l'individu, rendant ainsi l'identité individuelle dérivée de la communauté — position qualifiée de communautarisme radical<ref>Menkiti, Ifeanyi A., « Person and Community in African Traditional Thought », dans Richard A. Wright (dir.), ''African Philosophy: An Introduction'', 3e édition, Lanham, University Press of America, 1984, p. 171-181</ref>. Kwame Gyekye a défendu une position qu'il qualifie de « communautarisme modéré », arguant que la pensée africaine attribue une valeur intrinsèque à l'individu<ref>Gyekye, Kwame, « Person and Community in Akan Thought », dans Kwasi Wiredu et Kwame Gyekye (dir.), ''Person and Community: Ghanaian Philosophical Studies I'', Washington D.C., Council for Research in Values and Philosophy, 1992, p. 101-122</ref>. Le communautarisme modéré de Gyekye est construit sur trois piliers principaux : (1) la nature sociale et rationnelle de l'individu, (2) la reconnaissance des droits individuels, et (3) la suprématie morale de la communauté. ==== Le personisme de Nancy Myles ==== Nancy Oppongwaa Myles a proposé une position innovante qu'elle appelle le « personisme », qui cherche à dépasser le débat entre individualisme et communautarisme<ref>Myles, Nancy Oppongwaa, « 'The Individual' in the Individualism-Communitarianism Debate: In Defense of Personism », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 157-189</ref>. Selon Myles, le personisme conçoit l'individualité et la communalité comme des dispositions ou dimensions duales d'une seule entité — « la personne » — qui est naturellement et nécessairement à la fois individuelle et relationnelle, et interconnectée à différents niveaux avec d'autres personnes. Le personisme de Myles offre une synthèse conceptuelle qui évite les excès tant de l'individualisme libéral que du communautarisme radical. Il reconnaît que la personne humaine est constitutivement sociale tout en maintenant l'importance de l'agence et de l'autonomie individuelles. Cette position reflète la sophistication croissante du débat philosophique ghanéen sur la nature de la personne et de la communauté. === Les technologies émergentes et l'éthique africaine === Un développement récent dans la philosophie ghanéenne concerne l'application des concepts éthiques africains aux technologies émergentes, notamment l'intelligence artificielle et les soins de santé numériques. L'éthique Ubuntu a été proposée comme cadre pour guider le développement et le déploiement de l'IA dans le domaine de la santé, avec un accent sur l'équité et l'accès<ref>Institute for Ethics and AI, Technical University of Munich, « Ubuntu Ethics in AI for Healthcare: Enabling Equitable Care », op. cit.</ref>. Cette application de la philosophie africaine aux défis technologiques contemporains démontre la pertinence continue et l'adaptabilité des ressources conceptuelles africaines. Elle suggère que la philosophie ghanéenne n'est pas simplement tournée vers le passé ou préoccupée uniquement par des questions traditionnelles, mais qu'elle est capable d'offrir des perspectives originales sur les questions les plus pressantes de notre temps. === La tradition philosophique de Legon et le trans-modernisme === Martin Odei Ajei a articulé le concept de « trans-modernisme » comme caractérisant la tradition philosophique de Legon<ref>Ajei, Martin Odei, « Trans-modernism and a Legon Tradition of African Philosophy », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 1-25</ref>. Par trans-modernisme, Ajei entend une approche philosophique qui ne soit ni simplement moderne ni postmoderne, mais capable d'emprunter de manière sélective et critique aux différents courants de pensée. Cette approche refuse à la fois l'assimilation non critique de la modernité occidentale et le rejet wholesale de toute influence étrangère. Le trans-modernisme de la tradition de Legon se caractérise par quatre traits distinctifs : (1) un engagement avec la tradition philosophique analytique occidentale ; (2) une attention soutenue aux ressources conceptuelles des traditions africaines, particulièrement Akan ; (3) une préoccupation pour les questions de justice sociale et politique pertinentes pour l'Afrique contemporaine ; (4) une orientation cosmopolite qui cherche à contribuer aux débats philosophiques mondiaux tout en restant enracinée dans les préoccupations africaines. Cette caractérisation de la tradition philosophique ghanéenne offre un cadre utile pour comprendre sa contribution distinctive à la philosophie mondiale et sa capacité à naviguer entre particularisme et universalisme, entre tradition et modernité, entre enracinement local et portée globale. == Notes et références == {{references}} == Bibliographie == === Ouvrages de référence === * Hallen, Barry, ''Reading Wiredu'', Bloomington, Indiana University Press, 2021. * Wiredu, Kwasi, ''Philosophy and an African Culture'', Cambridge, Cambridge University Press, 1980. * Wiredu, Kwasi, ''Cultural Universals and Particulars : An African Perspective'', Bloomington, Indiana University Press, 1996. * Gyekye, Kwame, ''An Essay on African Philosophical Thought : The Akan Conceptual Scheme'', édition révisée, Philadelphia, Temple University Press, 1995. * Gyekye, Kwame, ''Tradition and Modernity : Philosophical Reflections on the African Experience'', New York, Oxford University Press, 1997. * Appiah, Kwame Anthony, ''In My Father's House : Africa in the Philosophy of Culture'', New York, Oxford University Press, 1992. * Appiah, Kwame Anthony, ''Cosmopolitanism : Ethics in a World of Strangers'', New York, W. W. Norton, 2006. * Lee, Christopher J., ''Kwame Anthony Appiah'', Londres, Routledge, 2021. === Ouvrages collectifs === * Wiredu, Kwasi et Kwame Gyekye (dir.), ''Person and Community : Ghanaian Philosophical Studies I'', Washington D.C., Council for Research in Values and Philosophy, 1992. * Ajei, Martin Odei (dir.), ''Disentangling Consciencism : Essays on Kwame Nkrumah's Philosophy'', Lanham, Lexington Books, 2016. * Atuire, Caesar A. et al. (dir.), ''Bioethics in Africa : Theories and Praxis'', Vernon Press, 2019. * Eze, Emmanuel (dir.), ''Postcolonial African Philosophy'', Oxford, Blackwell, 1997. * Wright, Richard A. (dir.), ''African Philosophy : An Introduction'', 3e édition, Lanham, University Press of America, 1984. === Articles de revues === * Ajei, Martin Odei, « Trans-modernism and a Legon Tradition of African Philosophy », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 1-25. * Ajei, Martin Odei, « Kwasi Wiredu's Consensual Democracy : Prospects for Practice in Africa », ''European Journal of Political Theory'', vol. 15, n° 4, 2016, p. 445-466. * Ajei, Martin Odei, « Educating Africans : Perspectives of Ghanaian Philosophers », ''Phronimon'', vol. 19, 2018, p. 1-15. * Jecker, Nancy S. et Caesar A. Atuire, « Realizing Ubuntu in Global Health : An African Approach to Global Health Justice », ''Public Health Ethics'', vol. 15, n° 3, 2022, p. 256-267. * Inusah, Husein, « Epistemic Decolonisation in African Higher Education : Beyond Current Curricular and Pedagogical Reformation », ''South African Journal of Higher Education'', vol. 37, n° 2, 2023, p. 87-105. * Myles, Nancy Oppongwaa, « 'The Individual' in the Individualism-Communitarianism Debate : In Defense of Personism », ''Legon Journal of the Humanities'', vol. 29, n° 2, 2018, p. 157-189. * Kwesi, Richmond, « The Will to Consensus », ''The Philosophical Forum'', vol. 55, n° 1, 2024, p. 45-62. === Chapitres d'ouvrages === * Ajei, Martin Odei, « Toward a Tradition of Ghanaian Political Philosophy », dans Leigh K. Jenco, Murad Idris et Megan C. Thomas (dir.), ''The Oxford Handbook of Comparative Political Theory'', Oxford, Oxford University Press, 2019, p. 125-141. * Gyekye, Kwame, « Person and Community in Akan Thought », dans Kwasi Wiredu et Kwame Gyekye (dir.), ''Person and Community : Ghanaian Philosophical Studies I'', Washington D.C., Council for Research in Values and Philosophy, 1992, p. 101-122. * Menkiti, Ifeanyi A., « Person and Community in African Traditional Thought », dans Richard A. Wright (dir.), ''African Philosophy : An Introduction'', 3e édition, Lanham, University Press of America, 1984, p. 171-181. * Wiredu, Kwasi, « Democracy and Consensus in African Traditional Politics : A Plea for a Non-Party Polity », dans Emmanuel Eze (dir.), ''Postcolonial African Philosophy'', Oxford, Blackwell, 1997, p. 303-312. === Revues spécialisées === * ''Legon Journal of the Humanities'', University of Ghana, Legon. * ''Phronimon'', University of South Africa Press. * ''South African Journal of Philosophy'', Taylor & Francis. * ''European Journal of Political Theory'', SAGE Publications. * ''Public Health Ethics'', Oxford Academic. * ''The Philosophical Forum'', Wiley-Blackwell. {{Autocat}} e0r2mlix30y9n13l48k8kfccetk7m01 Dictionnaire de philosophie/Empirisme 0 83122 768456 753845 2026-06-24T03:16:13Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768456 wikitext text/x-wiki {{DicoPhilo|Empirisme|lecture=oui}} L'''empirisme''' désigne un ensemble de doctrines philosophiques qui font de l’expérience sensible l’origine de toute connaissance ou, au minimum, de toute connaissance portant sur le monde. Cette position épistémologique soutient que nos idées, nos concepts et nos savoirs dérivent de ce que nous percevons par nos sens et ne peuvent, en dernière analyse, être justifiés qu’à l’aune de l’expérience. L’empirisme s’oppose ainsi à l’innéisme et au rationalisme, pour lesquels il existe des connaissances ou des principes indépendants de toute expérience sensible. == Définition et enjeux == === Les trois thèses de l’empirisme === On peut distinguer, de manière analytique, trois dimensions dans la doctrine empiriste, qui ne sont pas toujours soutenues ensemble ni avec la même intensité<ref>{{Ouvrage|auteur=Ayers, Michael|titre=Locke: Epistemology and Ontology|lieu=London|éditeur=Routledge|année=1993|pages=52-78}}</ref>. '''La thèse psychologique''' porte sur le mode d’acquisition de nos pensées et de nos contenus mentaux. L’empirisme psychologique affirme que les éléments constitutifs de toutes nos pensées – croyances, images, souvenirs, raisonnements – sont, directement ou indirectement, acquis par l’intermédiaire de l’expérience sensible. Sans contact avec le réel par nos sens (sens externes et sens interne), l’esprit ne pourrait former aucune idée. La métaphore classique, chez Locke, de l’''esprit-table rase'' exprime cette conviction : il n’y a pas de contenus mentaux innés, mais seulement des dispositions générales à recevoir et à travailler des matériaux fournis par l’expérience. '''La thèse épistémologique''' concerne la justification de nos croyances et de nos connaissances. L’empirisme épistémologique soutient que c’est l’expérience qui nous permet, en dernière instance, de juger si une croyance est vraie ou fausse, bien fondée ou arbitraire. La connaissance n’est assurée et garantie qu’autant que nos croyances se laissent éprouver par la confrontation à l’expérience sensible, entendue au sens large (perception, observation, expérimentation). On peut être empiriste de manière plus ou moins radicale : certains admettent que l’expérience est une source de connaissance parmi d’autres (aux côtés de la raison, par exemple) ; d’autres soutiennent, plus strictement, que toute connaissance authentique est nécessairement empirique et ''a posteriori''<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|lieu=Paris|éditeur=Vrin|année=2001|annéeorigine=1690|pages=Livre II, chap. I, § 2}}</ref>. '''La thèse sémantique''' porte enfin sur la signification des mots et des expressions linguistiques. Selon l’empirisme sémantique, ce qui confère un sens déterminé aux termes que nous utilisons est, au moins en partie, le lien qu’ils entretiennent avec les données de l’expérience sensible. Un mot qui ne renvoie à aucune expérience possible – actuelle ou possible pour un sujet humain – est dépourvu de contenu cognitif : il ne désigne rien, et relève du pseudo-concept, voire du pur « flatus vocis ». Hume formule ainsi un principe méthodologique : lorsque nous rencontrons un terme ou une proposition, nous devons nous demander de quelle impression sensible dérive l’idée correspondante ; si aucune impression ne peut être indiquée, le terme est suspect de vacuité<ref>{{Ouvrage|auteur=Hume, David|titre=Enquête sur l’entendement humain|lieu=Paris|éditeur=Flammarion|collection=GF|année=1983|annéeorigine=1748|pages=Section II}}</ref>. Ces trois thèses – psychologique, épistémologique et sémantique – peuvent être dissociées. Il est possible, par exemple, d’admettre que tous nos concepts dérivent de l’expérience (thèse psychologique) tout en soutenant qu’il existe des vérités nécessaires indépendantes de l’expérience (refus de la thèse épistémologique radicale), ou encore de refuser qu’un terme ait un sens s’il ne renvoie à aucune expérience possible (thèse sémantique) sans pour autant nier l’existence de connaissances ''a priori''. L’« empirisme » désigne en pratique une famille de positions articulant ces thèses à des degrés divers. === L’opposition empirisme–rationalisme === L’histoire de la philosophie moderne a souvent présenté l’empirisme et le rationalisme comme deux écoles antagonistes, particulièrement aux XVIIe et XVIIIe siècles. Cette dichotomie, bien qu’un peu schématique, permet de situer certains enjeux fondamentaux de l’épistémologie moderne. Pour les rationalistes comme René Descartes, Baruch Spinoza ou Gottfried Wilhelm Leibniz, la raison humaine est la source principale, voire exclusive, de la connaissance véritable. Certaines vérités universelles et nécessaires – mathématiques, métaphysiques, morales – peuvent être atteintes par la seule raison, indépendamment des incertitudes et des illusions de l’expérience sensible. Ces philosophes accordent une importance centrale aux idées innées, présentes dans l’esprit dès la naissance, et aux vérités ''a priori'', c’est-à-dire indépendantes de l’expérience. Descartes, par exemple, soutient que les idées de Dieu, d’infini ou de perfection ne peuvent être acquises par l’expérience du monde corporel, mais sont « nées avec nous » en tant que marques de leur auteur divin<ref>{{Ouvrage|auteur=Descartes, René|titre=Méditations métaphysiques|lieu=Paris|éditeur=Garnier-Flammarion|année=1979|annéeorigine=1641|pages=Méditation III}}</ref>. L’empirisme britannique, avec John Locke, George Berkeley et David Hume, s’oppose à cette conception. Ces auteurs soutiennent que l’expérience sensible, interne (réflexion sur les opérations de l’esprit) ou externe (perception des objets), est la seule source de nos connaissances factuelles. Toutes nos idées, même les plus générales et les plus abstraites, dérivent ultimement de ce que nous percevons. Il n’existe pas d’idées innées ; l’esprit à la naissance est comparable à une table rase (''tabula rasa'') qui se remplit progressivement par l’expérience<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|éditeur=Vrin|lieu=Paris|année=2001|annéeorigine=1690|pages=Livre II, chap. I, § 2}}</ref>. Les historiens de la philosophie ont cependant nuancé cette opposition tranchée. D’une part, les empiristes ne nient pas que la raison joue un rôle dans le processus de connaissance : ils refusent seulement la possibilité de connaissances ''purement'' rationnelles portant sur des faits concernant le monde, indépendamment de toute expérience. D’autre part, les rationalistes ne rejettent pas entièrement l’importance de l’expérience, notamment dans les sciences de la nature. La dichotomie empirisme/rationalisme fonctionne donc davantage comme un schéma classificatoire rétrospectif que comme la description exacte de deux camps homogènes. Kant lui-même, dans la ''Critique de la raison pure'', exploite cette opposition pour mettre en scène la « querelle » entre empiristes et rationalistes, avant de proposer sa propre solution transcendantale<ref>{{Ouvrage|auteur=Kant, Emmanuel|titre=Critique de la raison pure|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2012|annéeorigine=1781|pages=Préface à la seconde édition}}</ref>. == Les origines antiques et médiévales == Même si l’empirisme au sens moderne se constitue principalement aux XVIIe et XVIIIe siècles, ses prémisses remontent à l’Antiquité. Le terme grec d’''empeirikos'' (« empirique ») désignait, dans la médecine antique, une école qui s’opposait aux médecins « dogmatiques ». Les médecins empiriques refusaient de spéculer sur des causes cachées ou sur des essences inobservables ; ils privilégiaient l’observation directe des symptômes, la comparaison de cas et l’accumulation d’expériences cliniques. La guérison ne devait pas être expliquée par des théories abstraites, mais guidée par l’art de tirer parti d’expériences analogues antérieures. Sur le plan philosophique, certains aspects de l’empirisme se retrouvent dans le scepticisme, notamment chez Sextus Empiricus, dont le nom signale d’ailleurs la proximité avec la tradition médicale empirique. Les sceptiques pyrrhoniens accordent une grande importance à l’observation des phénomènes, tout en suspendant le jugement sur ce qui serait la réalité ultime ou la cause véritable. Ils défendent ainsi une forme d’« empirisme sans dogmatisme » : il faut se conformer aux apparences et à l’expérience vécue, mais renoncer à affirmer des thèses métaphysiques sur ce qui se trouve derrière elles. Au Moyen Âge, certains auteurs, sans être empiristes au sens strict, accordent à l’expérience un rôle méthodologique privilégié. Roger Bacon (vers 1214–1294) insiste sur la nécessité de l’expérimentation pour confirmer les raisonnements et dépasser les limites de la spéculation pure. Guillaume d’Ockham (vers 1285–1347), avec son principe de parcimonie (le « rasoir d’Ockham »), recommande de ne pas multiplier les entités sans nécessité et de s’en tenir autant que possible aux données de l’expérience pour construire nos ontologies<ref>{{Ouvrage|auteur=Guillaume d’Ockham|titre=Somme de logique|lieu=Mauvezin|éditeur=Trans-Europ-Repress|année=1988|annéeorigine=vers 1323|pages=Première partie}}</ref>. Cette exigence d’économie théorique anticipe certains réflexes empiristes modernes : ne pas supposer, au-delà de l’expérience, des entités qui n’apportent aucune différence observable. == L’empirisme moderne : Francis Bacon et la méthode expérimentale == === Francis Bacon : l’induction et le ''Novum Organum'' === Francis Bacon (1561–1626) occupe une place singulière dans l’histoire de l’empirisme. Il n’est pas empiriste au sens psychologique strict (il ne développe pas une théorie détaillée de l’origine des idées), mais il est l’un des premiers à formuler de manière systématique une méthode scientifique fondée sur l’observation, l’expérimentation et une induction méthodiquement contrôlée. Son ouvrage majeur, le ''Novum Organum'' (1620), se présente comme un nouvel instrument de connaissance, destiné à remplacer l’''Organon'' aristotélicien. Bacon critique vigoureusement deux attitudes intellectuelles qu’il juge stériles. D’un côté, les « empiriques » au sens péjoratif, comparés à des fourmis, se contentent d’amasser des observations hétéroclites sans en dégager des principes. De l’autre, les « dogmatiques » ou « rationnels », assimilés à des araignées, tissent à partir d’eux-mêmes des systèmes abstraits peu soucieux de l’expérience. Le bon chercheur doit être comme l’abeille : il recueille la matière première dans la nature et la transforme par l’activité de son entendement en une connaissance véritablement nouvelle<ref>{{Ouvrage|auteur=Bacon, Francis|titre=Novum Organum|lieu=Paris|éditeur=PUF|année=1986|annéeorigine=1620|pages=Livre I, aphorisme 95}}</ref>. La méthode baconienne repose sur une forme d’induction que Bacon cherche à rendre rigoureuse. Il propose de dresser des « tables » : table de présence (énumération des cas où le phénomène est présent), table d’absence (cas semblables où le phénomène est absent), table des degrés (cas où le phénomène varie d’intensité). En croisant ces séries de cas, le savant peut éliminer progressivement les fausses causes et isoler les conditions réellement pertinentes, ce que Bacon appelle la « forme » du phénomène étudié<ref>{{Ouvrage|auteur=Bacon, Francis|titre=Novum Organum|éditeur=PUF|lieu=Paris|année=1986|annéeorigine=1620|pages=Livre II, aphorismes 11-20}}</ref>. L’induction n’est plus une simple généralisation hâtive, mais une procédure méthodique d’exclusion. Bacon souligne également la nécessité de purifier l’esprit des « idoles » qui le trompent : idoles de la tribu (erreurs propres à la nature humaine en général), de la caverne (préjugés individuels), du marché (confusions liées au langage), du théâtre (illusions engendrées par les systèmes philosophiques et théologiques traditionnels)<ref>{{Ouvrage|auteur=Bacon, Francis|titre=Novum Organum|éditeur=PUF|lieu=Paris|année=1986|annéeorigine=1620|pages=Livre I, aphorismes 38-68}}</ref>. Cette critique des illusions cognitives sera reprise, sous des formes différentes, par de nombreux empiristes ultérieurs. == L’empirisme britannique classique == === John Locke : la table rase et l’origine des idées === John Locke (1632–1704) est généralement considéré comme le fondateur de l’empirisme moderne au sens strict. Son ''Essai philosophique concernant l’entendement humain'' (1690) propose une théorie systématique de la connaissance fondée sur l’expérience et un rejet argumenté de la doctrine des idées innées. Le premier livre de l’''Essai'' est consacré à la réfutation de l’innéisme. Locke examine l’argument selon lequel certaines vérités seraient universellement reconnues (par exemple, « tout ce qui est, est ») et que cette universalité d’assentiment prouverait leur caractère inné. Il objecte que les enfants en bas âge et les personnes atteintes de déficiences mentales ne manifestent aucun assentiment à ces prétendus principes universels. Si l’on rétorque que ces principes sont présents dans l’esprit mais non encore perçus explicitement, Locke répond qu’un principe qui ne devient effectif qu’à la faveur de l’expérience et de l’exercice de la pensée ne mérite pas d’être appelé inné : il est alors, en réalité, acquis<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|éditeur=Vrin|lieu=Paris|année=2001|annéeorigine=1690|pages=Livre I, chap. II}}</ref>. La thèse positive de Locke apparaît au début du second livre : « Je réponds d’un seul mot : de l’expérience ; en elle toute notre connaissance est fondée. » L’esprit à la naissance est comparable à une « chambre obscure » ou à une « feuille de papier blanche » qui se remplit progressivement par deux sources : la ''sensation'', qui nous donne les idées des objets extérieurs par nos cinq sens, et la ''réflexion'', qui est la perception des opérations de notre propre esprit (penser, douter, vouloir, raisonner, etc.)<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|éditeur=Vrin|lieu=Paris|année=2001|annéeorigine=1690|pages=Livre II, chap. I, § 2-4}}</ref>. Locke distingue les ''idées simples'', reçues passivement par la sensation ou la réflexion, et les ''idées complexes'', que l’entendement forme activement en combinant, comparant et abstrayant les idées simples. L’empirisme lockien n’est donc pas un simple sensualisme passif : si tout vient de l’expérience, l’esprit n’en est pas moins une puissance de synthèse, de comparaison et de généralisation<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|éditeur=Vrin|lieu=Paris|année=2001|annéeorigine=1690|pages=Livre II, chap. XII}}</ref>. Une autre distinction célèbre chez Locke oppose les ''qualités premières'' (ou primaires) aux ''qualités secondes''. Les premières – solidité, étendue, figure, mouvement ou repos, nombre – appartiennent réellement aux corps et sont inséparables de leur existence. Les secondes – couleurs, sons, saveurs, odeurs – ne sont que des puissances qu’ont les objets de produire en nous certaines sensations. Ainsi, la « rougeur » d’une tomate n’est pas une propriété qui serait dans la tomate au même sens que son étendue ; elle résulte de l’interaction entre la structure corpusculaire de l’objet et notre système perceptif<ref>{{Ouvrage|auteur=Locke, John|titre=Essai philosophique concernant l’entendement humain|éditeur=Vrin|lieu=Paris|année=2001|annéeorigine=1690|pages=Livre II, chap. VIII, § 9-26}}</ref>. Cette distinction ouvre une difficulté pour l’empirisme : si nous n’avons un accès direct qu’à nos idées, et non aux choses elles-mêmes, comment justifier l’affirmation selon laquelle les qualités premières « ressemblent » aux objets alors que les qualités secondes n’en sont que des effets subjectifs ? Locke maintient une forme de réalisme représentatif, mais la tension entre empirisme psychologique et réalisme métaphysique sera au cœur des critiques adressées à sa philosophie. === George Berkeley : l’idéalisme immatérialiste === George Berkeley (1685–1753), évêque anglican et philosophe, radicalise l’empirisme lockien en tirant de ses prémisses des conséquences inattendues. Dans les ''Principes de la connaissance humaine'' (1710) et les ''Trois dialogues entre Hylas et Philonous'' (1713), il développe un idéalisme immatérialiste : la « matière » entendue comme substance étendue existant indépendamment de tout esprit n’existe pas ; seuls existent des esprits et leurs idées. Le principe fondamental de Berkeley s’exprime dans la formule : ''esse est percipi aut percipere'' – « être, c’est être perçu ou percevoir ». Ce que nous appelons « choses matérielles » n’est rien d’autre qu’un ensemble stable et ordonné de perceptions : couleurs, formes, sons, résistances tactiles. Affirmer qu’un objet existe indépendamment de toute perception revient à le penser tout en prétendant qu’il peut exister sans être pensé : c’est, selon Berkeley, une contradiction performative<ref>{{Ouvrage|auteur=Berkeley, George|titre=Principes de la connaissance humaine|lieu=Paris|éditeur=Flammarion|collection=GF|année=1991|annéeorigine=1710|pages=§ 3-7}}</ref>. Berkeley critique la distinction lockienne entre qualités premières et secondes. Si l’on admet que les qualités secondes n’existent que dans l’esprit du percevant, pourquoi les qualités premières feraient-elles exception ? Nous ne percevons jamais une « étendue » ou un « mouvement » en soi, mais toujours une étendue colorée, un mouvement visible, une figure ressentie. Toutes nos perceptions ont la même nature mentale ; il n’y a aucune raison de réserver à certaines un statut objectif privilégié<ref>{{Ouvrage|auteur=Berkeley, George|titre=Principes de la connaissance humaine|lieu=Paris|éditeur=Flammarion|collection=GF|année=1991|annéeorigine=1710|pages=§ 9-15}}</ref>. On pourrait croire que cette position conduit au solipsisme : si les choses n’existent que comme perçues, cessent-elles d’exister lorsque personne ne les regarde ? Berkeley répond que les objets continuent d’exister parce qu’ils sont constamment perçus par Dieu, esprit infini. Le monde sensible est un système d’idées que Dieu produit de manière régulière dans les esprits finis. L’immatérialisme berkeleyien n’est donc pas un scepticisme, mais une métaphysique théiste : la constance de l’expérience est garantie par la fidélité de Dieu<ref>{{Ouvrage|auteur=Berkeley, George|titre=Trois dialogues entre Hylas et Philonous|lieu=Paris|éditeur=Flammarion|collection=GF|année=1998|annéeorigine=1713|pages=Troisième dialogue}}</ref>. L’empirisme de Berkeley se prolonge par une réflexion sur le langage et les idées générales. Il récuse la théorie lockienne des idées abstraites : nous ne pouvons pas nous représenter un « triangle en général » qui ne serait ni équilatéral, ni isocèle, ni scalène. Les mots généraux ne renvoient pas à des idées abstraites, mais à des idées particulières qui fonctionnent comme signes pour une multiplicité d’objets. La généralité appartient au langage, non aux représentations mentales<ref>{{Ouvrage|auteur=Berkeley, George|titre=Principes de la connaissance humaine|lieu=Paris|éditeur=Flammarion|collection=GF|année=1991|annéeorigine=1710|pages=Introduction, § 6-20}}</ref>. === David Hume : l’empirisme sceptique === David Hume (1711–1776) porte l’empirisme à un point de radicalité qui frôle le scepticisme. Son ''Traité de la nature humaine'' (1739–1740) et l’''Enquête sur l’entendement humain'' (1748) constituent l’aboutissement de l’empirisme britannique et mettent en lumière des difficultés profondes pour toute prétention à une connaissance nécessaire des faits. Hume commence par distinguer deux types de perceptions : les ''impressions'', qui sont les sensations, passions et émotions telles qu’elles se présentent avec vivacité à l’esprit, et les ''idées'', qui sont des copies affaiblies de ces impressions dans la pensée. Toutes les idées simples dérivent d’impressions correspondantes ; nous ne pouvons pas former l’idée d’une couleur que nous n’avons jamais vue ni celle d’une saveur que nous n’avons jamais goûtée. C’est le « principe de copie », qui fonde l’empirisme humien sur un critère précis de légitimité des idées<ref>{{Ouvrage|auteur=Hume, David|titre=Traité de la nature humaine|lieu=Paris|éditeur=Flammarion|collection=GF|année=1995|annéeorigine=1739|pages=Livre I, partie I, section I}}</ref>. Hume distingue ensuite deux sortes d’objets de la connaissance : les ''relations d’idées'' (vérités logiques et mathématiques), qui sont nécessaires mais purement analytiques, et les ''questions de fait'', qui concernent le monde et ne peuvent être établies que par l’expérience ''a posteriori''<ref>{{Ouvrage|auteur=Hume, David|titre=Enquête sur l’entendement humain|lieu=Paris|éditeur=Flammarion|collection=GF|année=1983|annéeorigine=1748|pages=Section IV, partie I}}</ref>. Sa contribution la plus célèbre est la critique de la causalité et du raisonnement inductif. Nous croyons spontanément que certains événements ''causent'' nécessairement d’autres (le feu cause la chaleur, le choc d’une bille entraîne le mouvement de l’autre). Or, selon Hume, nous ne percevons jamais cette prétendue « connexion nécessaire ». Nous observons seulement qu’un type de phénomène est constamment suivi d’un autre ; de cette conjonction constante naît dans notre esprit une ''habitude'' qui nous porte à attendre la répétition de cette succession. La nécessité causale n’est pas une relation objective entre les choses, mais un produit de notre esprit accoutumé<ref>{{Ouvrage|auteur=Hume, David|titre=Enquête sur l’entendement humain|lieu=Paris|éditeur=Flammarion|collection=GF|année=1983|annéeorigine=1748|pages=Section VII}}</ref>. D’où le problème de l’induction : comment justifier rationnellement le passage du passé au futur, du particulier au général ? Nous supposons que « le futur ressemblera au passé », mais ce principe ne peut être démontré ni par la raison (il n’est pas analytique) ni par l’expérience (il faudrait déjà l’utiliser pour fonder la valeur de l’induction). Hume conclut que nos croyances causales et nos anticipations ne reposent sur aucun fondement rationnel nécessaire, mais sur une propension naturelle de l’esprit. La raison n’en est pas moins condamnée à les avaliser, car nous ne pouvons vivre sans projeter l’avenir à partir du passé<ref>{{Ouvrage|auteur=Hume, David|titre=Enquête sur l’entendement humain|lieu=Paris|éditeur=Flammarion|collection=GF|année=1983|annéeorigine=1748|pages=Section IV, partie II}}</ref>. L’empirisme de Hume conduit encore à remettre en question l’idée d’un moi substantiel : lorsque nous nous livrons à l’introspection, nous ne rencontrons jamais un « moi » simple et identique, mais seulement un faisceau de perceptions changeantes. De même, les grands thèmes de la métaphysique traditionnelle (substance, âme, Dieu) excèdent les limites de ce qui peut être rattaché à une impression ; ils relèvent, selon Hume, de la fiction ou de la projection<ref>{{Ouvrage|auteur=Hume, David|titre=Traité de la nature humaine|lieu=Paris|éditeur=Flammarion|collection=GF|année=1995|annéeorigine=1739|pages=Livre I, partie IV, section VI}}</ref>. == Le sensualisme continental : Condillac == === Étienne Bonnot de Condillac : la statue sensible === Étienne Bonnot de Condillac (1715–1780) développe en France une variante originale de l’empirisme, souvent qualifiée de ''sensualisme''. Il soutient que toutes nos facultés mentales, y compris les plus élaborées, dérivent de la simple sensation. Son ''Traité des sensations'' (1754) propose une expérience de pensée célèbre : l’allégorie de la statue. Condillac invite à imaginer une statue organisée intérieurement comme un être humain, mais privée de toute idée. On réveille en elle, l’un après l’autre, ses sens, en commençant par l’odorat. Lorsque la statue sent pour la première fois une odeur de rose, elle n’est rien d’autre que cette odeur ; elle ne distingue pas encore un sujet qui sentirait un objet senti. Par la répétition et la comparaison des sensations, surgissent progressivement l’attention, la mémoire, le désir, puis le jugement, la réflexion et même la volonté. Toutes ces facultés, que Locke traitait comme distinctes de la sensation, ne sont pour Condillac que de la « sensation transformée »<ref>{{Ouvrage|auteur=Condillac, Étienne Bonnot de|titre=Traité des sensations|lieu=Paris|éditeur=Fayard|année=1984|annéeorigine=1754|pages=Première partie, chap. I-II}}</ref>. Condillac accorde une importance décisive au toucher, seul sens qui nous donne une véritable conscience de l’extériorité et de notre propre corps. Les autres sens nous livrent des « tableaux » sensibles sans que nous puissions distinguer ce qui est en nous et ce qui est hors de nous. C’est par la résistance éprouvée dans le toucher que nous apprenons à opposer notre corps à les corps extérieurs, et à constituer le monde comme un ensemble d’objets<ref>{{Ouvrage|auteur=Condillac, Étienne Bonnot de|titre=Traité des sensations|lieu=Paris|éditeur=Fayard|année=1984|annéeorigine=1754|pages=Troisième partie}}</ref>. Le sensualisme condillacien a profondément marqué la pensée française du XVIIIe siècle, la pédagogie des Lumières et certains développements matérialistes. Il radicalise l’intuition empiriste en cherchant à dériver non seulement les contenus de la pensée, mais les opérations mêmes de l’entendement, de la seule vie sensible. == La synthèse kantienne == === Kant : dépasser l’opposition entre empirisme et rationalisme === Emmanuel Kant (1724–1804), dans la ''Critique de la raison pure'' (1781), entreprend de dépasser l’opposition entre empirisme et rationalisme par une révolution qu’il qualifie lui-même de « copernicienne ». Il reconnaît à l’empirisme d’avoir insisté sur le rôle irremplaçable de l’expérience comme point de départ de la connaissance, et au rationalisme d’avoir mis en lumière l’existence de structures ''a priori''. Mais il refuse à l’un comme à l’autre leurs prétentions exclusives. Kant affirme d’emblée que « toute notre connaissance commence avec l’expérience », en ce sens qu’il ne se trouve rien dans l’entendement qui n’ait été d’abord donné sous forme d’intuition sensible. Mais il ajoute aussitôt qu’il ne s’ensuit pas que toute connaissance dérive de l’expérience : il y a des formes et des concepts ''a priori'' par lesquels l’esprit structure ce qui lui est donné<ref>{{Ouvrage|auteur=Kant, Emmanuel|titre=Critique de la raison pure|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2012|annéeorigine=1781|pages=Introduction, B 1}}</ref>. Kant distingue deux sources de la connaissance : la ''sensibilité'', par laquelle les objets nous sont donnés, et l’''entendement'', par lequel ils sont pensés. La sensibilité possède deux formes ''a priori'' : l’espace et le temps. Ce ne sont pas des propriétés des choses en soi, mais des formes de notre intuition : nous ne pouvons faire l’expérience d’objets qu’en les situant dans l’espace et dans le temps<ref>{{Ouvrage|auteur=Kant, Emmanuel|titre=Critique de la raison pure|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2012|annéeorigine=1781|pages=Esthétique transcendantale, §§ 1-8}}</ref>. L’entendement, de son côté, dispose de catégories ''a priori'' (substance, causalité, nécessité, etc.) qui unifient et structurent les données sensibles. La causalité, par exemple, n’est pas, comme chez Hume, une simple habitude psychologique ; elle est une condition de possibilité de l’expérience d’un monde d’objets soumis à des lois. Nous ne pourrions même pas reconnaître une succession objective d’événements si nous n’appliquions pas la catégorie de cause à effet<ref>{{Ouvrage|auteur=Kant, Emmanuel|titre=Critique de la raison pure|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2012|annéeorigine=1781|pages=Analogie de l’expérience, seconde analogie}}</ref>. Ainsi, contre l’empirisme strict, Kant soutient qu’il existe des jugements ''synthétiques a priori'' (en mathématiques et en physique théorique) qui, tout en étant nécessairement vrais, portent sur l’expérience possible et non sur de simples relations conceptuelles. Contre le rationalisme dogmatique, il limite néanmoins la validité de ces structures ''a priori'' au domaine des phénomènes : elles n’autorisent aucune connaissance de l’âme, du monde comme totalité ou de Dieu en tant que réalités en soi<ref>{{Ouvrage|auteur=Kant, Emmanuel|titre=Critique de la raison pure|lieu=Paris|éditeur=PUF|collection=Quadrige|année=2012|annéeorigine=1781|pages=Dialectique transcendantale}}</ref>. La synthèse kantienne reconnaît ainsi à l’empirisme la dépendance matérielle de la connaissance vis-à-vis de l’expérience, tout en réhabilitant des formes rationnelles ''a priori'' irréductibles. == L’empirisme contemporain == === Le positivisme logique et l’empirisme logique === Au XXe siècle, l’empirisme se renouvelle avec le Cercle de Vienne et le courant que l’on appelle ''positivisme logique'' ou ''empirisme logique''. Moritz Schlick, Rudolf Carnap, Otto Neurath et d’autres cherchent à articuler l’héritage empiriste avec la logique mathématique moderne (Frege, Russell) et certaines idées du ''Tractatus'' de Wittgenstein. Leur projet est de fonder une « conception scientifique du monde » en excluant la métaphysique comme discours dépourvu de sens. Selon le ''principe de vérification'', tel qu’ils le formulent, le sens d’un énoncé est lié à la méthode de sa vérification : un énoncé n’a de signification cognitive que s’il est soit analytique (vrai en vertu de sa forme logique), soit vérifiable empiriquement, c’est-à-dire testable en principe par l’observation ou l’expérience. Les propositions métaphysiques, qui ne sont ni analytiques ni vérifiables, doivent être rejetées comme des pseudo-énoncés<ref>{{Article|auteur=Carnap, Rudolf|titre=Le dépassement de la métaphysique par l’analyse logique du langage|périodique=Manifeste du Cercle de Vienne et autres écrits|éditeur=PUF|lieu=Paris|année=2010|annéeorigine=1931|pages=153-179}}</ref>. Les empiristes logiques défendent une conception unitaire de la science : tous les énoncés scientifiques, qu’ils portent sur la physique, la biologie ou la psychologie, devraient pouvoir être traduits, directement ou indirectement, en énoncés concernant des données d’expérience. Dans ''La construction logique du monde'' (1928), Carnap tente de reconstruire l’ensemble des concepts scientifiques à partir d’un langage phénoménal de base<ref>{{Ouvrage|auteur=Carnap, Rudolf|titre=Der logische Aufbau der Welt|lieu=Hamburg|éditeur=Felix Meiner Verlag|année=1998|annéeorigine=1928}}</ref>. Ce programme suscite cependant des objections. Le principe de vérification lui-même n’est ni analytique ni vérifiable : selon son propre critère, il serait donc dépourvu de sens. De plus, la plupart des énoncés scientifiques, notamment les lois générales, ne sont pas strictement vérifiables, car aucune expérience finie ne peut en épuiser le domaine d’application. Ces difficultés conduisent à des affaiblissements successifs du principe (vérifiabilité ''en principe'', puis simple confirmabilité) et à des débats internes au mouvement<ref>{{Article|auteur=Schlick, Moritz|titre=Signification et vérification|périodique=Manifeste du Cercle de Vienne et autres écrits|éditeur=PUF|lieu=Paris|année=2010|annéeorigine=1932|pages=337-370}}</ref>. === Karl Popper et le falsificationnisme === Karl Popper (1902–1994) propose une alternative à la vérification empiriste. Dans ''La logique de la découverte scientifique'' (1934), il soutient que le critère de démarcation entre science et non-science n’est pas la vérifiabilité, mais la ''réfutabilité'' (ou falsifiabilité). Une théorie est scientifique si elle expose, en principe, à la possibilité d’être réfutée par l’expérience, c’est-à-dire si elle exclut certains états de choses observables<ref>{{Ouvrage|auteur=Popper, Karl|titre=La logique de la découverte scientifique|lieu=Paris|éditeur=Payot|année=1973|annéeorigine=1934|pages=chap. 1}}</ref>. Popper accepte la critique humienne de l’induction : aucune accumulation d’observations ne peut vérifier définitivement une loi universelle. En revanche, une seule observation contraire suffit, en droit, à la réfuter. La science progresse par « conjectures et réfutations » : des hypothèses audacieuses sont proposées, soumises à des tests sévères, et écartées lorsqu’elles échouent. Les théories qui résistent le mieux à la critique sont ''corroborées'', mais jamais définitivement prouvées<ref>{{Ouvrage|auteur=Popper, Karl|titre=Conjectures et réfutations|lieu=Paris|éditeur=Payot|année=1985|annéeorigine=1963|pages=chap. 1}}</ref>. Cette conception rencontre à son tour des objections. En pratique, on ne teste jamais une hypothèse isolée, mais un ensemble d’énoncés théoriques et d’hypothèses auxiliaires (ce que Duhem et Quine ont mis en lumière). Face à un résultat expérimental récalcitrant, il est toujours possible de modifier une hypothèse auxiliaire plutôt que la théorie centrale. L’histoire des sciences montre aussi que des théories fécondes ont été maintenues malgré des anomalies persistantes<ref>{{Ouvrage|auteur=Lakatos, Imre|titre=Histoire et méthodologie des sciences|lieu=Paris|éditeur=PUF|année=1994|annéeorigine=1978|pages=chap. 1}}</ref>. === Willard Van Orman Quine : holisme et empirisme naturalisé === Willard Van Orman Quine (1908–2000) transforme en profondeur l’héritage empiriste. Dans « Les deux dogmes de l’empirisme » (1951), il remet en cause deux piliers du positivisme logique : la distinction nette entre énoncés analytiques (vrais en vertu de la signification) et énoncés synthétiques (vrais en vertu des faits), et le réductionnisme selon lequel chaque énoncé pourrait être testé isolément par l’expérience<ref>{{Ouvrage|auteur=Quine, Willard Van Orman|titre=Du point de vue logique|lieu=Paris|éditeur=Vrin|année=2003|annéeorigine=1953|pages=« Les deux dogmes de l’empirisme », p. 49-81}}</ref>. Quine défend un ''holisme épistémologique'' : nos croyances ne font pas face à l’expérience une à une, mais comme un système global. Le « tribunal de l’expérience » juge l’ensemble de notre théorie du monde, et nous avons, en principe, une grande liberté pour décider où porter les révisions en cas de conflit. On peut choisir de sacrifier un énoncé particulier, une hypothèse auxiliaire, ou même des principes logiques de base, si l’on juge ce remaniement moins coûteux pour la cohérence globale du système<ref>{{Ouvrage|auteur=Quine, Willard Van Orman|titre=Du point de vue logique|lieu=Paris|éditeur=Vrin|année=2003|annéeorigine=1953|pages=p. 67-73}}</ref>. Quine propose en outre une ''épistémologie naturalisée''. Plutôt que de chercher à fonder les sciences sur des certitudes indubitables, l’épistémologie doit être intégrée au corpus de la science elle-même, et notamment à la psychologie. Elle étudie alors comment un organisme humain, en interaction avec un environnement physique, en vient à élaborer un réseau de croyances de plus en plus sophistiqué. L’empirisme devient ainsi une thèse méthodologique interne au projet scientifique, et non plus une doctrine fondationnelle située au-dessus de la science<ref>{{Ouvrage|auteur=Quine, Willard Van Orman|titre=Relativité de l’ontologie et autres essais|lieu=Paris|éditeur=Aubier|année=2008|annéeorigine=1969|pages=« L’épistémologie devenue naturelle », p. 83-105}}</ref>. == Critiques et limites de l’empirisme == L’empirisme, sous ses différentes formes, a suscité de nombreuses critiques, portant à la fois sur la fiabilité de l’expérience, sur le statut des vérités nécessaires et sur la conception de l’observation. === Les limites de l’expérience sensible === Une première famille d’objections met en cause la fiabilité des sens. Les expériences d’illusion, d’hallucination, de mirage, montrent que la perception peut nous tromper. L’empiriste répond qu’il faut corriger les perceptions particulières par d’autres perceptions, croiser les témoignages sensoriels, multiplier les observations. Mais cela suppose déjà que l’on dispose de critères pour distinguer les expériences plus fiables des expériences trompeuses, et ces critères ne sont pas eux-mêmes fournis immédiatement par les sens. De plus, de nombreux objets des sciences contemporaines (particules élémentaires, champs quantiques, structures cosmologiques lointaines) ne sont pas directement observables. L’empiriste doit alors admettre que la connaissance ne porte pas seulement sur ce qui est immédiatement donné, mais sur des entités théoriques postulé(es) pour expliquer des régularités observables. On parle alors d’« observabilité indirecte » : nous ne voyons pas les électrons, mais les traces qu’ils laissent dans des chambres à bulles ou les effets qu’ils produisent dans des dispositifs expérimentaux. L’empirisme strict, qui voulait fonder la signification sur la seule donnée sensible, se trouve ainsi mis à l’épreuve. === Le problème des vérités nécessaires === Une difficulté classique pour l’empirisme concerne le statut des vérités nécessaires et universelles, notamment en mathématiques et en logique. Comment expliquer que « 2 + 2 = 4 » ou que « nul n’est à la fois carré et circulaire » soient valables indépendamment de toute expérience, si toute connaissance découle de l’expérience, toujours contingente et particulière ? Hume, on l’a vu, répond en distinguant nettement les ''relations d’idées'' et les ''questions de fait'' : les premières sont connues indépendamment de l’expérience et ne nous apprennent rien sur le monde ; les secondes dépendent de l’expérience et ne sont jamais nécessaires. Une telle solution revient à reconnaître l’existence d’un domaine de connaissance ''a priori'', mais en le cantonnant aux vérités purement analytiques. D’autres, comme John Stuart Mill, ont tenté de soutenir que même les vérités arithmétiques seraient le résultat d’une induction à partir de manipulations d’objets, ce qui ferait des mathématiques une forme de généralisation empirique ; cette thèse est cependant jugée aujourd’hui peu convaincante. === Le problème de l’induction === Le problème de l’induction, formulé avec une clarté exemplaire par Hume, frappe au cœur de l’empirisme. Si tout notre savoir des lois naturelles repose sur des inférences inductives, et si ces inférences ne peuvent être justifiées ni par la logique (elles ne sont pas nécessaires) ni par l’expérience (toute tentative de justification empirique serait circulaire), alors la prétention de l’empirisme à fonder solidement la connaissance scientifique semble compromise. Des réponses comme le falsificationnisme de Popper ou le holisme de Quine cherchent moins à « résoudre » le problème qu’à l’intégrer dans une conception plus modeste et plus pragmatique de la rationalité scientifique. === La charge théorique de l’observation === Les travaux de Norwood Russell Hanson, Thomas Kuhn et Paul Feyerabend ont mis en lumière le caractère ''chargé de théorie'' de l’observation. Nous n’observons pas des « faits bruts » qui viendraient ensuite être interprétés ; nous voyons toujours déjà le réel à travers des catégories, des schèmes, des attentes, des instruments conceptuels. Un même phénomène – par exemple la trajectoire d’un corps dans un champ magnétique – n’est pas « vu » de la même manière par un physicien newtonien et un physicien relativiste<ref>{{Ouvrage|auteur=Kuhn, Thomas|titre=La structure des révolutions scientifiques|lieu=Paris|éditeur=Flammarion|collection=Champs|année=2008|annéeorigine=1962|pages=chap. X}}</ref>. Cette thèse affaiblit l’idée empiriste d’une base observationnelle neutre, qui servirait de tribunal ultime pour arbitrer entre théories. Elle montre que le rapport entre théorie et expérience est circulaire et réciproque : les théories orientent l’observation autant qu’elles en résultent. Certains en ont tiré des conclusions relativistes ; d’autres, plus modérés, en font un argument pour concevoir l’empirisme non comme une doctrine de fondation, mais comme une exigence méthodologique de confrontation permanente entre théories et phénomènes. == Prolongements et héritages contemporains == L’empirisme, loin d’être une doctrine figée, s’est diversifié au XXe et au XXIe siècles. Sous le nom de ''naturalisme'', de ''pragmatisme'' ou d’''empirisme pragmatique'', on retrouve l’intuition fondamentale selon laquelle notre connaissance du monde, pour être légitime, doit s’enraciner dans l’expérience, tout en reconnaissant la complexité des médiations conceptuelles et sociales qui structurent cette expérience. Dans les sciences cognitives, les débats entre innéisme et empirisme se poursuivent sous des formes renouvelées. Les travaux de Noam Chomsky sur une « grammaire universelle » innée ont ravivé l’idée de structures mentales préformées, tandis que d’autres approches insistent sur la plasticité des réseaux neuronaux et sur la capacité d’apprendre des régularités complexes à partir de données sensorielles massives. En philosophie de l’esprit et du langage, de nombreuses théories du contenu mental et de la référence gardent une inspiration empiriste, en faisant dépendre la signification des mots et des états mentaux de nos interactions causales avec l’environnement. Parallèlement, des courants comme le contextualisme, l’encyclopédisme sémantique ou les théories des concepts enracinés dans l’action revisitent la thèse empiriste selon laquelle il n’y a pas de sens sans lien, au moins indirect, avec l’expérience possible. L’empirisme demeure ainsi, sous des formes souvent transformées, l’une des grandes orientations de la pensée philosophique. Il rappelle constamment une exigence critique : ne pas se satisfaire de constructions spéculatives détachées de toute expérience, mais exiger que nos théories, nos concepts et nos croyances puissent, d’une manière ou d’une autre, être confrontés à ce que le monde nous donne effectivement à vivre et à percevoir. == Notes et références == {{references}} ==Bibliographie== ===Textes classiques=== * Bacon, Francis, ''Novum Organum'', Paris, PUF, 1986 [1620] * Berkeley, George, ''Principes de la connaissance humaine'', Paris, Flammarion, 1991 [1710] * Berkeley, George, ''Trois dialogues entre Hylas et Philonous'', Paris, Flammarion, 1998 [1713] * Condillac, Étienne Bonnot de, ''Traité des sensations'', Paris, Fayard, 1984 [1754] * Hume, David, ''Traité de la nature humaine'', 3 volumes, Paris, Flammarion, 1995 [1739-1740] * Hume, David, ''Enquête sur l'entendement humain'', Paris, Flammarion, 1983 [1748] * Locke, John, ''Essai philosophique concernant l'entendement humain'', édition abrégée, Paris, Vrin, 2001 [1690] ===Études critiques=== * Ayers, Michael, ''Locke: Epistemology and Ontology'', 2 volumes, London, Routledge, 1993 * BonJour, Laurence, ''In Defense of Pure Reason'', Cambridge, Cambridge University Press, 1998 * Chappell, Vere (dir.), ''The Cambridge Companion to Locke'', Cambridge, Cambridge University Press, 1994 * Deleuze, Gilles, ''Empirisme et subjectivité. Essai sur la nature humaine selon Hume'', Paris, PUF, 1953 * Garrett, Don, ''Cognition and Commitment in Hume's Philosophy'', Oxford, Oxford University Press, 1997 * Stroud, Barry, ''Hume'', London, Routledge & Kegan Paul, 1977 * Winkler, Kenneth, ''Berkeley: An Interpretation'', Oxford, Clarendon Press, 1989 ===Sur l'empirisme contemporain=== * Carnap, Rudolf, ''La construction logique du monde'', Paris, Vrin, 2002 [1928] * Popper, Karl, ''La logique de la découverte scientifique'', Paris, Payot, 1973 [1934] * Quine, Willard Van Orman, ''Du point de vue logique'', Paris, Vrin, 2003 [1953] * Quine, Willard Van Orman, ''Le mot et la chose'', Paris, Flammarion, 1977 [1960] ==Articles connexes== * {{Page|Connaissance}} * {{Page|Épistémologie}} * {{Page|Expérience}} * {{Page|Idées innées}} * {{Page|Induction}} * {{Page|Rationalisme}} * {{Page|Scepticisme}} * {{Page|Sensation}} {{AutoCat}} pjk5fyjxosypyguq2y29pqbt0mrpso4 Dictionnaire de philosophie/Épistémologie 0 83123 768457 766470 2026-06-24T03:16:24Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768457 wikitext text/x-wiki {{DicoPhilo|Épistémologie|lecture=oui}} == Introduction == === L’épistémologie comme discipline philosophique === ==== 1.1 Définition et champ épistémologique ==== L’épistémologie, dont le nom dérive des termes grecs ''epistêmê'' (connaissance, science) et ''logos'' (étude, discours), se présente d’abord comme la branche de la philosophie consacrée à l’examen de la connaissance. Cette définition, en apparence simple, recouvre cependant un domaine d’enquête bien plus vaste et complexe qu’il n’y paraît. L’épistémologie ne se limite pas à décrire les différentes formes de connaissance ; elle engage une réflexion approfondie sur la nature même de ce que nous prétendons connaître, sur les conditions de possibilité de cette connaissance et sur les normes qui en gouvernent l’acquisition, la conservation et la mise à l’épreuve. Historiquement, l’épistémologie s’est constituée progressivement en discipline autonome au cours du XIX{{e}} siècle. Les questions qui la définissent remontent à l’Antiquité, mais l’apparition du terme et la formation de la discipline comme telle répondent à des besoins philosophiques nouveaux. Le mot ''épistémologie'' est attesté en français dès 1876, sous la plume d’Auguste Penjon, dans un article intitulé « Un métaphysicien anglais contemporain : M. J. F. Ferrier », publié dans la ''Revue philosophique de la France et de l’étranger'' (t. II, 1876, p. 130-167)<ref>Penjon, A. “Un métaphysicien anglais contemporain: M. J. F. Ferrier.” ''Revue philosophique de la France et de l'étranger'', vol. 2, 1876, pp. 130–67. JSTOR, http://www.jstor.org/stable/41071286. Accessed 23 Nov. 2025.</ref>. En 1901, le terme est repris dans la traduction française de l’''Essay on the Foundations of Geometry'' de Bertrand Russell (''Essai sur les fondements de la géométrie'', Paris, Gauthier-Villars), due à Albert Cadenat et revue par Russell et Louis Couturat, où ''epistemology'' devient ''épistémologie'' dans l’introduction. Le mot demeure toutefois d’un usage rare jusqu’au début du XX{{e}} siècle, où il se stabilise notamment avec son entrée dans le supplément du ''Larousse illustré'' (1906) et avec l’emploi systématique qu’en fait Émile Meyerson dans ''[[s:Identité et réalité|Identité et réalité]]'' (1908). Cette cristallisation tardive est significative : l’épistémologie moderne naît moins d’une simple prolongation des interrogations antiques que de la nécessité de penser les conséquences philosophiques des profondes transformations des sciences à l’époque moderne, à partir notamment de Galilée, Descartes et Newton. On peut dire que l’épistémologie articule au moins quatre questions centrales. D’abord une question définitionnelle : qu’est-ce que la connaissance ? Ensuite une question de la justification : dans quelles conditions une croyance peut-elle être dite justifiée ? Vient ensuite la question des sources : d’où vient la connaissance, quelles en sont les origines légitimes ? Enfin, une question de domaine : que pouvons-nous connaître, et quelles sont les limites de notre savoir ? Ces quatre interrogations forment un ensemble solidaire : on ne peut répondre à l’une sans présupposer, même implicitement, une réponse aux autres. Elles fournissent encore aujourd’hui la trame de la plupart des débats épistémologiques. ==== 1.2 Distinction entre épistémologie générale et épistémologies sectorielles ==== Il importe d’emblée de distinguer deux usages du terme ''épistémologie'', selon que l’on s’intéresse aux principes généraux de la connaissance ou à ses modalités dans des domaines particuliers. L’épistémologie générale s’attache aux principes supposés universels qui régiraient toute forme de connaissance, indépendamment de l’objet auquel elle s’applique. Elle s’efforce de dégager les traits communs à la connaissance mathématique, à la connaissance empirique, à la connaissance morale ou religieuse, et plus largement à tout ce qui prétend au titre de savoir. Inversement, on parle d’''épistémologies sectorielles'' ou spécialisées : épistémologie des sciences physiques, de la biologie, de la psychologie, des sciences humaines et sociales, des mathématiques, de la morale, de la religion, de l’histoire, etc. Ces approches reconnaissent que les critères de validité et les procédures de justification varient fortement selon les domaines. Une théorie scientifique ne se justifie pas de la même manière qu’une thèse morale ; une découverte mathématique ne repose pas sur les mêmes types de preuves qu’une affirmation historique ; et le statut épistémique des « preuves » diffère profondément entre la physique expérimentale, l’économie, la psychanalyse ou la philosophie politique. Cette distinction est particulièrement significative pour notre époque. L’ambition d’une approche générale, qui chercherait un fondement ou une norme épistémique unique pour tous les savoirs, se heurte sans cesse à la pluralité apparemment irréductible des méthodes, des normes et des formes de justification qui organisent effectivement la pratique des sciences et des autres domaines de connaissance. En sens inverse, les démarches spécialisées risquent de morceler le savoir en compartiments étanches, sans véritable dialogue entre eux. La tension, souvent féconde, entre ces deux perspectives – la recherche de principes communs et l’attention aux spécificités de chaque domaine – demeure l’un des traits marquants de l’épistémologie contemporaine. ==== 1.3 L’épistémologie comme métacognition ==== On peut aussi caractériser l’épistémologie comme une réflexion de second degré : elle prend pour objet la connaissance elle-même. Elle « pense la pensée », s’attache à connaître la connaissance, et interroge les conditions de possibilité de l’interrogation philosophique. De ce fait, elle entretient un rapport singulier à son objet. L’épistémologue n’est pas un simple observateur extérieur placé face à un phénomène qu’il contemplerait de loin ; il participe lui-même à l’activité cognitive qu’il cherche à élucider. La réflexion épistémologique est une réflexion de l’intérieur, engagée, qui s’applique à l’une des pratiques – connaître – dont elle use déjà pour se déployer. Ce caractère réflexif engendre une forme de circularité dont les philosophes ont souvent souligné l’inévitabilité. Lorsque nous examinons les critères de validité de la connaissance, nous mobilisons déjà certaines idées sur ce qui compte comme bon raisonnement, bonne preuve, bonne source de croyance. Lorsque nous élaborons une théorie de la justification, nous recourons à des raisonnements que cette théorie devrait, en principe, être en mesure de justifier. Cette circularité n’est pas un vice qu’il faudrait éliminer à tout prix, mais le trait constitutif de toute réflexion qui porte sur ses propres conditions de possibilité. La philosophie antique l’avait déjà perçu : la question « comment connaître ? » suppose toujours un minimum de connaissance, ne serait-ce que celle de la langue dans laquelle on formule la question ou des notions qu’elle emploie. ==== 1.4 Relations avec les autres disciplines philosophiques ==== L’épistémologie ne forme pas un îlot isolé au sein de la philosophie. Elle entretient des rapports étroits avec plusieurs autres branches, dont elle dépend en partie tout en influençant leur évolution. Avec la logique, elle partage le souci de la validité du raisonnement. La logique s’intéresse aux formes d’inférence, aux structures argumentatives indépendamment de tout contenu ; elle dit dans quelles circonstances une conclusion suit nécessairement de prémisses données. L’épistémologie, pour sa part, se demande dans quelles conditions un raisonnement, même formellement valide, peut fonder un véritable savoir. Un argument peut être impeccable du point de vue logique et néanmoins ne pas constituer un bon fondement de connaissance si les prémisses elles-mêmes ne sont pas justifiées. Les relations avec la métaphysique sont plus complexes et ont varié au cours de l’histoire. Longtemps, et notamment dans la philosophie antique et médiévale, ces deux disciplines n’étaient guère séparées : on ne pouvait pas se demander « comment connaissons-nous ? » sans commencer par se demander « qu’est-ce qui existe ? ». Avec Kant, un infléchissement décisif se produit : il ne s’agit plus seulement de dériver la connaissance de la structure de l’être, mais de montrer que c’est la structure de notre faculté de connaître qui fixe ce que nous pouvons légitimement dire de la réalité. Aujourd’hui encore, métaphysique et épistémologie disposent d’une certaine autonomie, mais elles dialoguent constamment : toute position sur ce qu’il y a implique une conception, même implicite, de ce que nous pouvons en connaître, et toute théorie de la connaissance s’accompagne d’engagements métaphysiques. Les liens avec l’éthique, et plus largement avec la philosophie pratique, se sont resserrés au cours des dernières décennies. On s’interroge de plus en plus sur les rapports entre ce que nous devons croire et la manière dont nous devons vivre. Les vertus épistémiques – honnêteté intellectuelle, souci de la vérité, ouverture d’esprit, prudence dans le jugement, courage intellectuel – sont devenues un terrain privilégié d’échanges entre épistémologie et éthique. La question de « l’éthique de la croyance » a pris une importance particulière : avons-nous le droit, moralement, de croire sur la base d’indices insuffisants ? À l’inverse, avons-nous des devoirs épistémiques en tant que citoyens, par exemple l’obligation de nous informer sérieusement avant de nous prononcer sur des enjeux politiques ou sanitaires ? Enfin, l’épistémologie entretient des affinités évidentes avec la philosophie de l’esprit. Toutes deux s’intéressent à la croyance, à l’intention, à l’expérience consciente. Mais là où la philosophie de l’esprit décrit les phénomènes mentaux tels qu’ils se présentent effectivement chez les êtres doués de pensée, l’épistémologie évalue ces phénomènes à la lumière de normes de vérité et de justification. Une certitude subjective peut être psychologiquement très forte sans pour autant satisfaire aux exigences minimales de la justification rationnelle. ==== 1.5 L’épistémologie entre science et philosophie ==== Une tension profonde traverse l’épistémologie contemporaine. D’un côté, on éprouve le désir de rendre l’étude de la connaissance elle-même plus « scientifique », en l’appuyant sur les résultats empiriques des sciences cognitives, de la psychologie, de la linguistique ou de l’anthropologie. De l’autre, on tient à préserver la dimension normative et réflexive proprement philosophique de l’enquête sur le savoir. Cette tension renvoie à un tournant majeur du XX{{e}} siècle. En 1969, Willard Van Orman Quine publie l’article ''Epistemology Naturalized'', où il propose de renoncer à l’ancienne ambition de fonder la science sur des principes premiers indubitables. L’épistémologie, selon lui, doit devenir une partie des sciences empiriques : plutôt que de chercher des fondements absolus au savoir scientifique, il s’agit de comprendre comment les processus cognitifs effectifs d’un organisme biologique, l’être humain, produisent et stabilisent la science dans ses rapports avec l’environnement. La connaissance est alors étudiée comme un phénomène naturel parmi d’autres. Cette orientation naturaliste a profondément modifié le paysage épistémologique. La plupart des épistémologues reconnaissent aujourd’hui l’importance des données empiriques sur le fonctionnement réel de la cognition humaine. Mais beaucoup considèrent qu’une telle « naturalisation » ne doit pas conduire à abandonner toute prétention normative. Même nourrie par les sciences de la nature et les sciences humaines, l’épistémologie reste chargée de formuler des normes : elle ne se contente pas de décrire ce que les gens croient ou comment ils raisonnent, elle s’interroge sur ce qu’ils devraient croire et sur la façon dont ils devraient former leurs croyances. La relation entre l’épistémologie et les disciplines qui prennent la science pour objet – histoire, sociologie et psychologie des sciences, anthropologie des savoirs, neurobiologie de la cognition – s’en trouve reconfigurée. L’épistémologie emprunte désormais largement à ces disciplines, qui lui fournissent une connaissance plus précise de nos capacités et de nos limites cognitives. En retour, elle offre un cadre conceptuel pour interpréter ces résultats empiriques et poser la question décisive : ce que les agents font effectivement n’est pas nécessairement ce qu’ils sont fondés à faire du point de vue de la recherche de la vérité. === Enjeux contemporains de l'épistémologie === ==== 2.1 Pluralité d'approches et renouvellement du champ ==== L’épistémologie contemporaine ne se caractérise plus par la domination d’une seule école de pensée, mais par une diversité méthodologique marquée : elle met en œuvre une pluralité d’approches qui non seulement ne s’excluent pas mutuellement, mais s’articulent de plus en plus étroitement les unes aux autres. L’épistémologie analytique, héritière de la tradition anglo-américaine, conserve une place importante. Elle poursuit l’examen des concepts fondamentaux de connaissance, de justification et de croyance, en cherchant à les analyser avec rigueur, souvent à l’aide des outils de la logique formelle. Cette approche maintient un souci de précision conceptuelle qui reste décisif. Le problème dit de Gettier (1963), qui a remis en cause l’analyse classique de la connaissance comme « croyance vraie justifiée », demeure une référence théorique majeure dans une large part de la recherche en épistémologie analytique. Depuis quelques décennies, l’épistémologie formelle s’est développée de manière considérable. Elle applique des méthodes mathématiques, en particulier probabilistes, à l’étude de la connaissance et de la croyance. Le bayésianisme épistémologique, qui modélise la justification en termes de degrés de confiance (ou ''crédences'') ajustés à la lumière de nouvelles preuves, a profondément modifié la manière de penser le raisonnement scientifique et l’inférence. L’épistémologie naturalisée, inspirée par Quine et développée notamment par Alvin Goldman, vise à ancrer l’étude de la connaissance dans les sciences empiriques : psychologie, neurosciences et, plus largement, sciences cognitives. Cette approche rejette la thèse selon laquelle l’épistémologie serait purement ''a priori'' et relèverait de la seule analyse conceptuelle. Elle insiste sur le fait que comprendre comment nous connaissons effectivement requiert de comprendre comment fonctionne notre cerveau et comment nos processus cognitifs interagissent avec leur environnement. L’épistémologie des vertus, qui se développe à partir des années 1980 avec les travaux de Linda Zagzebski, Lorraine Code, Ernest Sosa et d’autres, établit un lien explicite entre épistémologie et éthique. Elle ne demande pas seulement : ''qu’est-ce que la connaissance ?'', mais aussi : ''quel type de sujet connaissant convient-il d’être ?'' et ''quelles qualités intellectuelles devons-nous cultiver ?'' Cette approche met en rapport l’excellence épistémique et les vertus intellectuelles, et réinscrit la réflexion sur la connaissance dans une réflexion plus large sur la formation du caractère. L’épistémologie sociale, dont l’appellation s’impose à la fin du XX{{e}} siècle notamment grâce aux travaux d’Alvin Goldman et de Steve Fuller, reconnaît que la connaissance n’est pas produite par des individus isolés. Le savoir se constitue toujours dans un contexte social, par le témoignage, la coopération, les pratiques collectives et le fonctionnement des institutions scientifiques. Cette prise en compte a ouvert un champ d’enquête étendu : comment les groupes produisent-ils de la connaissance ? Comment se structurent les hiérarchies épistémiques ? Quels rôles jouent le pouvoir et les institutions dans la formation, la circulation et la légitimation des croyances ? L’épistémologie féministe, depuis les travaux des années 1980 sur la ''standpoint theory'' (théorie du point de vue) jusqu’aux analyses intersectionnelles récentes, a montré que le « point de vue de nulle part » de l’observateur scientifique relevait d’une fiction théorique. La situation sociale d’une personne, en particulier son expérience de domination ou de privilège, conditionne en partie ce qu’elle peut connaître et la manière dont elle peut le connaître. Les épistémologies féministes mettent ainsi en lumière la dimension située de toute entreprise de connaissance. ==== 2.2 Les défis du XXI{{e}} siècle : technologie, information, polarisation ==== L’épistémologie n’a sans doute jamais été aussi étroitement liée aux enjeux sociaux et politiques qu’aujourd’hui. Trois défis majeurs structurent le paysage intellectuel actuel. ===== 2.2.1 La crise de la post-vérité et des fausses informations ===== Le phénomène désigné par le terme « post-vérité », identifié comme « mot de l’année » par Oxford Dictionaries en 2016, ne se réduit pas à une augmentation quantitative du mensonge. Il désigne plutôt une situation où les faits objectifs exercent une influence moindre, dans la formation de l’opinion publique, que les appels aux émotions et aux convictions personnelles. Les recherches actuelles distinguent plusieurs phénomènes connexes : la désinformation (fausses informations diffusées intentionnellement), la mésinformation (fausses informations diffusées sans intention de tromper) et ce que l’on appelle, en anglais, les ''fake news'' (fausses nouvelles délibérément fabriquées pour tromper, le plus souvent à des fins politiques ou commerciales). La préoccupation centrale des épistémologues ne porte pas seulement sur la présence de contenus mensongers, qui a toujours existé, mais sur la transformation du contexte épistémique dans lequel ces informations circulent. Les algorithmes de recommandation des réseaux sociaux, en cherchant à maximiser l’« engagement », produisent des bulles informationnelles dans lesquelles chacun est exposé de manière privilégiée à des contenus qui confirment ses croyances préalables. La diffusion d’un message dépend alors moins de la véracité de son contenu que de sa capacité à susciter des réactions affectives fortes. Le phénomène de « post-vérité » soulève des questions épistémologiques fondamentales : comment distinguer le vrai du faux lorsque les critères de crédibilité se fragmentent ? Quels repères permettent d’identifier une expertise légitime ? Comment reconstituer une base commune de faits partageables ? Ces interrogations ont des conséquences directes pour la démocratie, pour la santé publique (par exemple dans les débats sur la vaccination ou le changement climatique) et pour la place de la science dans l’espace public. ===== 2.2.2 L’intelligence artificielle et ses implications épistémiques ===== L’intelligence artificielle, en particulier les grands modèles de langage et l’apprentissage profond (''deep learning''), pose des questions épistémologiques inédites. Ces systèmes reposent sur des processus partiellement opaques : même leurs concepteurs ne parviennent pas toujours à rendre compte de la manière dont ils aboutissent à telle ou telle conclusion. On parle alors du « problème de la boîte noire ». Plusieurs questions épistémiques se posent. D’abord, peut-on dire que les systèmes d’IA « savent » quelque chose ? Produisent-ils du savoir ou bien seulement des corrélations et des régularités extraites de masses de données ? Ensuite, comment évaluer la fiabilité d’un résultat fourni par une IA ? Les hallucinations des grands modèles de langage, c’est-à-dire la production de réponses fausses mais plausibles, appellent un examen attentif de la différence entre compétence réelle et simple apparence de compétence. La collecte et le traitement des données sur lesquelles s’entraînent ces systèmes soulèvent également des questions proprement épistémiques. Les données ne sont jamais neutres : elles reflètent les structures sociales dans lesquelles elles sont produites, avec leurs biais, leurs inégalités et leurs angles morts. Un algorithme entraîné sur des données biaisées reproduira et amplifiera ces biais. De plus, le recours massif à l’IA entraîne, selon plusieurs travaux récents, une mutation de nos pratiques de connaissance : on passe d’une science centrée sur l’explication causale à des approches de plus en plus guidées par les données, qui privilégient la mise au jour de corrélations au détriment de l’identification des rapports causaux et de la compréhension fine des mécanismes sous-jacents. ===== 2.2.3 Les injustices épistémiques et le pouvoir ===== Miranda Fricker a mis en évidence, dans ses travaux fondateurs sur l’injustice épistémique, que la connaissance n’est pas seulement une affaire individuelle, mais aussi une question de pouvoir et de justice. Elle distingue deux formes principales d’injustice épistémique. L’''injustice testimoniale'' se produit lorsqu’une personne reçoit un crédit épistémique diminué en raison de préjugés sociaux. Cette forme d’injustice se manifeste, par exemple, lorsque la parole d’une femme scientifique est systématiquement moins prise au sérieux que celle d’un collègue masculin, lorsqu’un patient issu d’une minorité racisée voit ses plaintes médicales relativisées, ou encore lorsque l’on refuse d’emblée toute crédibilité à une personne en raison de troubles psychiatriques. L’''injustice herméneutique'' se produit lorsqu’une personne ne dispose pas, au sein de sa communauté, des ressources conceptuelles nécessaires pour interpréter son expérience. Historiquement, les femmes victimes de harcèlement sexuel ne disposaient pas d’un concept stabilisé pour nommer ce qu’elles subissaient ; l’élaboration du terme et du cadre conceptuel a été nécessaire. Les migrants peuvent manquer de mots et de notions adéquates pour comprendre leur situation d’exclusion sociale. Une personne neurodivergente peut ne pas parvenir à exprimer son expérience avec les concepts disponibles dans sa langue et sa culture. Ces formes d’injustice produisent des effets tangibles : une personne dont le témoignage n’est pas pris en compte ne recevra pas le traitement médical approprié ; un groupe dépourvu de cadre herméneutique pour analyser son oppression demeurera largement invisible aux yeux des institutions susceptibles de le soutenir. Remédier à ces injustices exige le développement de vertus épistémiques correctrices : l’humilité épistémique (reconnaître les limites de son propre savoir), l’ouverture d’esprit (admettre la possibilité de se tromper), mais aussi la justice testimoniale (être attentif aux préjugés qui affectent la crédibilité) et la sensibilité herméneutique (reconnaître les lacunes conceptuelles collectives et travailler à les combler). ==== 2.3 Entre universalisme et pluralisme : la diversité épistémologique ==== Un enjeu majeur du XXI{{e}} siècle pour l’épistémologie réside dans la tension entre l’universalisme, c’est-à-dire l’idée qu’il existerait une seule forme de connaissance pleinement légitime – souvent identifiée à la science occidentale moderne –, et le pluralisme épistémologique, qui souligne que différentes cultures, traditions et pratiques produisent des connaissances valables selon des voies diverses. L’épistémologie occidentale a longtemps considéré comme allant de soi que le modèle du savoir était celui des sciences physiques modernes : savoir empiriquement contrôlable, mathématiquement formalisable, objectif et impersonnel. Cette conception s’est établie au prix d’une marginalisation, voire d’un effacement, des épistémologies non occidentales, des savoirs autochtones et des pratiques traditionnelles de connaissance. Les ''épistémologies du Sud'' (expression développée notamment par Boaventura de Sousa Santos) reposent sur la thèse selon laquelle le savoir occidental n’est qu’une épistémologie parmi d’autres. Les savoirs écologiques, médicaux ou mathématiques issus d’Afrique, d’Asie ou d’Amérique latine ne sauraient être ramenés à de simples esquisses imparfaites de la science occidentale. Ils constituent des systèmes épistémiques cohérents et des modes de connaissance du monde dotés de leurs propres critères de rigueur et de validation. Cette reconnaissance pose des questions épistémologiques complexes : comment comparer et évaluer des épistémologies profondément différentes sans imposer les critères de l’une à toutes les autres ? Comment articuler pluralisme épistémologique et responsabilité scientifique, notamment en matière de santé publique ou d’écologie globale ? Le pluralisme conduit-il nécessairement à un relativisme excessif, ou peut-on maintenir des exigences critiques tout en reconnaissant la pluralité des formes de savoir ? ==== 2.4 Normes épistémiques et pratiques effectives ==== Une tension fondamentale parcourt l’épistémologie contemporaine : celle qui distingue les normes épistémiques idéales des pratiques effectives de production de savoir. L’épistémologie traditionnelle interrogeait prioritairement la question : ''comment doit-on connaître ?'' Elle élaborait des normes de justification considérées comme universellement valables. Mais une telle approche tendait à négliger les conditions concrètes de la connaissance : comment les savants et les citoyens connaissent-ils effectivement ? Quelles sont les contraintes sociales, techniques, psychologiques dans lesquelles se forme le savoir ? Les sciences cognitives ont établi que les processus cognitifs humains s’écartent nettement des modèles rationnels des manuels de logique. Le raisonnement humain présente de nombreux biais systématiques : biais de confirmation (tendance à rechercher et privilégier les informations qui confirment nos croyances), biais de disponibilité (tendance à surévaluer ce qui vient aisément à l’esprit), aversion à la perte, pensée motivée, et bien d’autres encore. L’épistémologie dite non idéale se donne pour tâche de comprendre comment des sujets réels, avec leurs limites et leurs biais, peuvent néanmoins parvenir à une connaissance solide. Il ne s’ensuit pas qu’il convienne de renoncer aux normes. Il s’agit plutôt de reconnaître que les normes épistémiques doivent être réalistes, c’est-à-dire compatibles avec ce que nous sommes effectivement capables de faire. Une norme qui exigerait l’omniscience logique serait dépourvue de pertinence pour des agents finis comme nous ; inversement, une norme qui admettrait tout indistinctement ne serait plus une norme. ==== 2.5 Interdisciplinarité croissante ==== L’épistémologie ne se conçoit plus comme une discipline abstraite isolée du reste du savoir. Elle entretient désormais un dialogue constant avec d’autres domaines de recherche. Elle s’articule d’abord aux sciences cognitives, qui permettent de comprendre comment se forment concrètement les croyances et comment notre cerveau traite l’information. Elle s’appuie également sur la sociologie et l’histoire des sciences pour analyser les contextes sociaux et institutionnels de production du savoir, en reconnaissant que la connaissance est toujours située historiquement et socialement. Elle s’articule ensuite à la philosophie politique, lorsqu’il s’agit d’examiner les enjeux démocratiques du savoir : qui a droit à la parole ? Quels savoirs sont pris en compte dans l’espace public ? Comment promouvoir une forme de justice épistémique dans des sociétés traversées par de fortes inégalités ? Elle s’articule également à l’éthique appliquée pour traiter des questions morales posées par les nouvelles technologies de l’information et les nouvelles formes de responsabilité liées à l’usage du savoir. Enfin, la linguistique et l’herméneutique contribuent à éclairer la manière dont le langage structure notre compréhension du monde, et dont les ressources conceptuelles partagées façonnent ce qui peut être reconnu comme objet de connaissance. Cette configuration interdisciplinaire ne doit pas être tenue pour un signe de fragilité. Elle témoigne au contraire de ce que les questions épistémiques ne peuvent plus être abordées séparément des pratiques effectives du savoir et des enjeux sociopolitiques auxquels nos sociétés sont confrontées. ==== 2.6 Éléments de synthèse ==== L’épistémologie contemporaine se caractérise par une diversité méthodologique féconde : rigueur analytique et attention aux données empiriques, ambition normative et souci descriptif, visée universaliste et sensibilité au pluralisme cohabitent et interagissent de façon constructive. Les défis de la post-vérité, de l’intelligence artificielle, des injustices épistémiques et de la polarisation confèrent une urgence nouvelle à l’enquête épistémologique : loin de constituer une discipline détachée des enjeux sociaux, elle se présente désormais comme l’un des outils conceptuels indispensables pour penser les questions les plus pressantes de nos sociétés. == Première partie : Problèmes fondamentaux de la connaissance == === Chapitre 1 : Qu'est-ce que la connaissance ? === ==== 1.1 La définition traditionnelle : croyance vraie justifiée ==== ===== Origines platoniciennes ===== Le ''Théétète'' de Platon, dialogue composé au IV{{e}} siècle avant notre ère, constitue la première enquête systématique sur la nature de la connaissance dans la tradition philosophique occidentale. La question centrale — « qu'est-ce que la connaissance ? » — qui structure ce dialogue ordonnera une large part de la réflexion épistémologique ultérieure, en fixant les termes mêmes dans lesquels la problématique de la connaissance sera posée jusqu'à l'époque contemporaine.<ref>Platon, ''Théétète'', 142a-210b. Traduction française : Louis-André Dorion, ''Platon. Théétète'', Paris, Flammarion, 1990.</ref> À travers un échange entre Socrate et le jeune mathématicien Théétète, Platon examine successivement plusieurs définitions de la connaissance, en montrant l'insuffisance constitutive de chacune d'elles, tout en accumulant progressivement les exigences que doit satisfaire une compréhension adéquate de ce phénomène. ====== L'insuffisance de la perception ====== Le dialogue progresse par élimination méthodique. Théétète propose d'abord que la connaissance s'identifie à la perception (''aisthêsis''). Cette première définition, bien qu'en apparence triviale, mérite une attention sérieuse, car elle établit un point de départ contre lequel toute théorie ultérieure de la connaissance devra se positionner. Socrate procède à la réfutation de cette thèse selon trois axes argumentatifs distincts, chacun révélant un aspect différent de l'inadéquation de la perception comme critère de la connaissance. '''La vulnérabilité de la perception aux apparences trompeuses''' Le premier argument porte sur la ''fiabilité'' de la perception. Les phénomènes perceptifs sont susceptibles d'induire en erreur. Un bâton immergé dans l'eau paraît brisé, bien qu'il demeure intact. Les images réfléchies par un miroir semblent se situer dans le miroir lui-même, alors qu'elles ne sont que des reflets. Les objets éloignés paraissent plus petits que les objets proches, bien que leur grandeur réelle soit indépendante de la distance. Cette susceptibilité à l'illusion soulève une difficulté fondamentale : si la connaissance s'identifiait à la perception, alors l'illusion perceptive constituerait une forme de connaissance, ce qui est contradictoire. Par définition, la connaissance ne peut être fausse : c'est une condition ''sine qua non'' de la connaissance que d'être conforme à la réalité. L'illusion, au contraire, nous trompe. Dès lors, si nous reconnaissons que nous pouvons être abusés par la perception, nous devons admettre que la perception seule — la simple saisie immédiate par les sens — ne constitue pas la connaissance.<ref>Platon, ''Théétète'', 151e-186e. Sur cette première réfutation, voir : Lesley Brown, « The Theaetetus », dans C. H. Shields (dir.), ''The Blackwell Guide to Plato's Republic'', Oxford, Blackwell, 2003, p. 401-425.</ref> '''L'inaccessibilité perceptive des entités universelles et abstraites''' Le second argument a une portée métaphysique plus profonde. Il existe une classe de réalités que nous affirmons connaître sans pour autant les percevoir directement : les propriétés universelles et abstraites. La ''justice'', la ''beauté'', le ''nombre'', l'''égalité'' — ces entités ne sont pas susceptibles d'être saisies par les sens. On peut certes percevoir des actes justes ou injustes, des objets beaux ou laids, des collections de trois pommes ou de trois pierres. Mais on ne perçoit jamais la justice ''en elle-même'', la beauté ''en elle-même'', ou le nombre ''trois'' pris indépendamment de toute instanciation matérielle. Or nous affirmons communément que nous ''connaissons'' ces réalités abstraites. Un géomètre connaît les propriétés des triangles, non par perception sensorielle, mais par raisonnement et démonstration. Un législateur, ou un philosophe politique, prétend connaître ce qu'est la justice, non par simple observation d'actes particuliers, mais par compréhension de principes universels qui les régissent. Si la connaissance était identique à la perception, ces affirmations seraient dépourvues de sens. Pourtant, elles expriment une conviction profondément ancrée dans notre pratique cognitive ordinaire. Il faut donc reconnaître que la perception ne peut être le critère exhaustif de la connaissance. '''L'instabilité ontologique de l'objet perçu''' Le troisième argument concerne le statut ontologique de ce qui est perçu. Les objets de la perception sont soumis au changement perpétuel (''panta rhei'', « tout s'écoule »). La rose que vous contemplez aujourd'hui sera fanée demain. La jeunesse cède à la vieillesse. Les cités se transforment avec le temps. Or la connaissance semble porter sur quelque chose de stable, d'immuable. Les vérités géométriques demeurent identiques à elles-mêmes. Les propriétés mathématiques ne changent pas. Même si tous les triangles concrets venaient à disparaître, les théorèmes de géométrie resteraient vrais. Comment la perception, qui ne nous met en rapport qu'avec l'éphémère et le mutable, pourrait-elle nous donner accès à ce qui est permanent et intelligible ? Socrate illustre cette difficulté par une remarque significative : un enfant peut très bien voir des figures géométriques sans pour autant savoir ce qu'est la géométrie. Le propre de la connaissance, contrairement à la simple perception, est de saisir l'universel dans le particulier, le stable dans le changeant, le principe à travers ses instanciations singulières. ====== L'insuffisance de la croyance vraie ====== Confronté aux difficultés de sa première proposition, Théétète en formule une seconde, plus élaborée : la connaissance consiste en une ''croyance vraie'' (''doxa alêthês''). Cette définition représente un progrès conceptuel appréciable, en ce qu'elle reconnaît que la connaissance implique un jugement — une prise de position mentale quant à l'état du monde — tout en exigeant que ce jugement soit objectivement conforme à la réalité. Socrate identifie cependant un défaut majeur dans cette formulation, qui le conduit à soulever une question d'une acuité remarquable : « Comment comprendre la possibilité de l'erreur ? »<ref>Platon, ''Théétète'', 187a-200c. Voir également : Michel Narcy, « Doxa et alèthéia chez Platon », ''Proceedings of the Boston Area Colloquium in Ancient Philosophy'', vol. 11, 1995, p. 1-25.</ref> Le problème peut être énoncé ainsi : la définition de la connaissance comme croyance vraie suppose que deux états doxastiques distincts — posséder la vérité et être dans l'erreur — relèvent tous deux du même genre, la ''croyance''. Mais comment un même sujet peut-il, à propos d'un même domaine, croire le vrai et croire le faux ? Comment la fausseté et la vérité peuvent-elles toutes deux se présenter sous la forme de croyances ? Socrate éclaire ce problème au moyen d'un exemple judiciaire particulièrement instructif : celui d'un jury persuadé par une argumentation mensongère mais extraordinairement convaincante. Imaginons que les jurés croient sincèrement qu'un accusé est innocent, en fondant leur conviction sur un témoignage faux mais apparemment irréfutable. Or l'accusé est en réalité ''innocent'' — de sorte que la croyance des jurés, bien qu'elle repose sur un témoignage mensonger, coïncide accidentellement avec la réalité.<ref>Platon, ''Théétète'', 200e-201a.</ref> Nous nous trouvons ici devant une situation épistémiquement étrange : les jurés possèdent à proprement parler une ''croyance vraie'' — leur jugement correspond à l'état de fait réel. Pourtant, nous hésitons à dire qu'ils ''savent'' que l'accusé est innocent. Ils ont simplement bénéficié d'une coïncidence heureuse. Leur conviction vraie demeure dépourvue de véritable valeur épistémique, car elle repose sur des raisons inappropriées, sur une justification défectueuse ou trompeuse. Cet exemple met en lumière l'insuffisance structurelle de la définition « croyance vraie ». Il existe des cas où une croyance possède bien le prédicat de vérité sans pour autant mériter le statut de connaissance — en particulier lorsque la vérité de la croyance est due au hasard, ou lorsqu'elle n'est pas née d'un lien correct entre la réalité et les raisons qui la soutiennent. ====== La condition de ''logos'' : vers la connaissance comme croyance vraie justifiée ====== Théétète, ayant reconnu l'insuffisance de la croyance vraie, propose une troisième définition, sensiblement plus sophistiquée : la connaissance est une ''croyance vraie accompagnée d'un logos'' (''doxa alêthês meta logou''). Cette formulation introduit un nouvel élément constitutif : l'exigence de justification ou de raison. Le terme ''logos'' revêt, dans le contexte platonicien, une signification complexe et polyvalente. Il ne désigne pas simplement la ''parole'' (bien que ce soit une traduction possible), mais plutôt un ensemble d'exigences convergentes. Un ''logos'', c'est d'abord une ''explication rationnelle'', c'est-à-dire la capacité à rendre compte des raisons pour lesquelles les choses sont comme elles sont. C'est aussi une ''justification'', l'ensemble des raisons ou des preuves qui soutiennent légitimement une affirmation. Le ''logos'' renvoie encore à un ''principe intelligible'', la saisie du fondement ou de la cause d’une chose, et, plus largement, à une ''articulation conceptuelle'', la capacité à distinguer, ordonner et relier les éléments d'un savoir.<ref>Platon, ''Théétète'', 201c. Sur l'interprétation du ''logos'' platonicien en rapport avec la justification, voir : Timothy Chappell, ''Reading Plato's Theaetetus'', Indianapolis/Cambridge, Hackett, 2004, p. 198-215.</ref> L'apport décisif de cette troisième définition est de reconnaître que la connaissance n'est pas une simple possession passive de vérités, mais une compréhension active, capable de se justifier et de s'exposer. Savoir, ce n'est pas seulement croire quelque chose de vrai, c'est aussi ''pouvoir rendre raison'' de ce que l'on affirme — disposer de raisons appropriées qui fondent légitimement la croyance en question. ====== Portée historique et fécondité théorique ====== Cette troisième définition — la connaissance comme croyance vraie justifiée — établit un cadre théorique qui exercera une influence considérable sur la réflexion épistémologique occidentale. Elle cristallise trois exigences fondamentales : 1. L’'''exigence de vérité''' : la connaissance porte nécessairement sur ce qui est réel et vrai. Une croyance fausse, si sincère et fermement tenue soit-elle, ne constitue jamais une connaissance. 2. L’'''exigence de conviction mentale''' : la connaissance implique un engagement doxastique du sujet — une prise de position cognitive qui affirme, qui assume. La simple compréhension abstraite d'une proposition, dépourvue de croyance effective, ne suffit pas pour parler de connaissance au sens fort. 3. L’'''exigence de justification''' : la connaissance requiert un fondement rationnel approprié. Une croyance vraie ''par accident'', dont la vérité résulte d'une coïncidence fortuite ou d'une chaîne causale inadéquate, ne mérite pas le statut de connaissance. La vérité doit être ''gagnée'' par le sujet, ancrée dans des raisons pertinentes. Bien que Platon lui-même considère que cette définition demeure insuffisante — le ''Théétète'' se conclut en effet sur une ''aporia'', une impasse théorique — cette tripartition de la connaissance en vérité, croyance et justification s'imposera comme un schéma directeur de la réflexion épistémologique, de la philosophie moderne (Descartes, Locke) jusqu'aux épistémologues analytiques contemporains, de Russell à nos jours. Ce n'est qu'en 1963, avec l'article devenu classique d'Edmund Gettier, que l'on montrera, à partir de contre-exemples subtils, que cette définition « platonicienne » de la connaissance comme ''croyance vraie justifiée'' ne fournit pas encore des conditions à la fois nécessaires et suffisantes de la connaissance, relançant ainsi dans un contexte philosophique transformé la question platonicienne d'origine : « Qu'est-ce que la connaissance ? »<ref>Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, n° 6, 1963, p. 121-123.</ref> La remarquable persistance de cette question — posée avec une acuité inédite dans le ''Théétète'' — témoigne de la profondeur inépuisable de l'analyse platonicienne et de la fécondité durable de la grille de lecture qu'elle propose pour penser la connaissance : articulation de la vérité, de la croyance et du ''logos'' justificatif. ===== La structure tripartite : croyance, vérité, justification ===== À partir du XX{{e}} siècle, l’analyse ''tripartite'' de la connaissance (souvent désignée par l’acronyme ''JTB'', pour ''Justified True Belief'') s’impose, dans l’épistémologie analytique, comme le schéma de base.<ref>Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, n° 6, 1963, p. 121-123. Cet article court mais influent marque le tournant qui conduit à l’adoption généralisée du sigle « JTB ».</ref> On peut la formuler, dans sa version élémentaire, de la façon suivante : S connaît que p si et seulement si : # p est vrai (condition de vérité) # S croit que p (condition de croyance) # S est justifié(e) à croire que p (condition de justification) Ces trois conditions sont tenues pour nécessaires et conjointement suffisantes pour qu’il y ait connaissance : si l’une manque, il n’y a pas connaissance ; si les trois sont satisfaites, on considère que S sait que p.<ref>Roderick Chisholm, ''Theory of Knowledge'', Prentice-Hall, 1966 (1{{re}} édition). Cet ouvrage de référence formalise la structure tripartite pour l’épistémologie analytique.</ref> Il faut toutefois signaler une précision historique. Présenté dans cette forme canonique, le schéma JTB n’a pas été proposé explicitement comme « définition traditionnelle » par les grands épistémologues antérieurs à Gettier. Descartes, Kant, Russell et d’autres défendent plutôt l’idée que la connaissance exige une forme de certitude : non pas une justification quelconque, mais une justification censée exclure, en droit, la possibilité de l’erreur.<ref>René Descartes, ''Méditations métaphysiques'', Méditation Première, 1641 ; Immanuel Kant, ''Critique de la raison pure'', Introduction, A1-A6 / B1-B10.</ref> Ce n’est qu’après la publication, en 1963, du bref article d’Edmund Gettier critiquant l’analyse tripartite, que l’on a commencé à qualifier rétrospectivement ce schéma de « définition traditionnelle » de la connaissance. ===== La condition de vérité ===== La première condition énonce que l’on ne peut connaître que ce qui est vrai. Si je crois que Paris est la capitale de la Belgique, ma croyance est fausse ; quelle que soit par ailleurs ma sincérité, la force de ma conviction ou la cohérence de mes autres croyances, elle ne peut valoir comme connaissance.<ref>Jaakko Hintikka, ''Knowledge and Belief. An Introduction to the Logic of the Two Notions'', Cornell University Press, 1962, p. 29-45.</ref> On rencontre ici une asymétrie nette : une croyance peut être vraie sans être une connaissance (parce qu’elle est vraie par chance ou pour des raisons insuffisantes), mais aucune connaissance ne peut être fausse. Cette exigence, apparemment évidente, ouvre sur des questions philosophiques importantes. Qu’est-ce qui fait qu’une proposition est vraie ? Dans quelles conditions une croyance peut-elle être dite « conforme à la réalité » ?<ref>Alfred Tarski, « The Semantic Conception of Truth and the Foundations of Semantics », ''Philosophy and Phenomenological Research'', vol. 4, 1944, p. 341-376.</ref> Les différentes théories de la vérité — théories de la correspondance, de la cohérence, conceptions pragmatistes ou déflationnistes — proposent des analyses divergentes du rapport entre croyance et monde.<ref>Michael Lynch (dir.), ''The Nature of Truth'', MIT Press, 2001.</ref> Dans le cadre de l’analyse JTB, on adopte en général une position minimale : on suppose que la vérité est une propriété objective des propositions, indépendante de ce que nous en pensons ; certaines propositions sont vraies, d’autres fausses, et cette différence ne dépend ni de notre assentiment ni de notre ignorance. ===== La condition de croyance ===== La seconde condition affirme que la connaissance implique la croyance. On ne peut pas connaître une proposition à laquelle on ne croit pas. Dire : « Je sais que p, mais je n’y crois pas » revient à se contredire.<ref>Bertrand Russell, ''The Problems of Philosophy'', Oxford University Press, 1912, chap. VII.</ref> La connaissance comporte donc au moins une croyance vraie, même si cela ne suffit pas à la constituer. Le terme de croyance demande cependant à être précisé. On entend généralement par là une attitude propositionnelle : une manière pour un sujet de se rapporter à une proposition en la tenant pour vraie.<ref>Roderick Chisholm, ''Person and Object'', Allen & Unwin, 1976, p. 8-27 ; Franz Brentano, ''Psychology from an Empirical Standpoint'', Routledge, 1973 (traduction anglaise de l’édition allemande de 1874).</ref> La croyance se distingue ainsi de l’espoir (où je souhaite que quelque chose soit vrai), du doute (où je suspends mon jugement) ou de l’hypothèse (où je considère provisoirement une proposition sans y adhérer pleinement). Reste à savoir si l’on croit toujours « tout ou rien ». Dans l’analyse JTB, la croyance est supposée binaire : soit je crois que le ciel est bleu, soit je ne le crois pas. Or les sciences cognitives contemporaines et l’épistémologie formelle s’accordent à décrire nos états doxastiques comme des degrés de confiance disposés sur un continuum — les ''crédences'' : je peux être plus ou moins sûr que p.<ref>Isaac Levi, ''The Fixation of Belief and Its Undoing'', Cambridge University Press, 1991 ; Darren Bradley, ''A Critical Introduction to Bayesian Epistemology'', Bloomsbury, 2015.</ref> Dans cette perspective, croire consiste à attribuer à p une certaine probabilité subjective. L’analyse classique adopte, par simplification, un modèle binaire. Ce choix oriente la réflexion vers la seule présence ou absence de croyance, et laisse en arrière-plan les variations de confiance et les révisions progressives que les approches bayésiennes prennent pour objet. ===== La condition de justification ===== La troisième condition est la plus délicate : la croyance doit être justifiée. Cela signifie qu’il existe des raisons suffisantes de tenir la proposition pour vraie, des raisons qui distinguent cette croyance d’une simple supposition accidentellement correcte.<ref>Alvin Goldman, ''Epistemology and Cognition'', Harvard University Press, 1986, p. 59-90.</ref> Ces raisons peuvent être de types variés : observations empiriques, inférences déductives ou inductives, témoignages de sources jugées fiables, démonstrations mathématiques, arguments philosophiques, etc. On peut rendre cette exigence plus concrète par deux exemples contrastés. Dans le premier cas, Maria sort de chez elle et voit que le ciel est bleu. Sur la base de cette expérience perceptive, elle forme la croyance que le ciel est bleu. Cette croyance est vraie, Maria l’entretient effectivement, et elle paraît étayée par une perception ordinaire, non trompeuse, de son environnement. Il semble naturel de dire qu’elle sait que le ciel est bleu.<ref>BonJour, Laurence, ''The Structure of Empirical Knowledge'', Harvard University Press, 1985, p. 38-45.</ref> Dans le second cas, Marco croit lui aussi que le ciel est bleu, mais sans l’avoir observé. Il lance une pièce de monnaie en décidant arbitrairement que « face = le ciel est bleu » et « pile = le ciel est noir ». La pièce tombe sur face, et il en conclut que le ciel est bleu. Sa croyance est vraie (le ciel est effectivement bleu ce jour-là), mais elle n’est nullement justifiée : le résultat d’un tirage à pile ou face ne fournit aucune raison pertinente de trancher une question météorologique.<ref>Gettier, op. cit., p. 121.</ref> La justification trace ainsi une frontière nette : elle distingue les croyances vraies qui méritent le nom de connaissances (parce qu’elles reposent sur de bonnes raisons) des croyances vraies qui n’en sont pas (parce qu’elles ne sont vraies que par coïncidence). Dans le schéma JTB, cette troisième condition a précisément pour fonction d’exclure les cas où la vérité de la croyance serait purement fortuite.<ref>Alvin Goldman, « A Causal Theory of Knowing », ''The Journal of Philosophy'', vol. 64, n° 12, 1967, p. 357-372.</ref> Reste à préciser ce qu’est une justification adéquate. Est-elle entièrement déterminée par des éléments internes à la perspective du sujet (des raisons auxquelles il a accès par réflexion) ou dépend-elle aussi de facteurs externes (la fiabilité effective de ses processus cognitifs, les conditions objectives dans lesquelles il forme ses croyances) ?<ref>William Alston, ''Epistemic Justification. Essays in the Theory of Knowledge'', Cornell University Press, 1989.</ref> Cette interrogation conduit à l’opposition classique entre internalisme et externalisme en épistémologie, qui organise une grande partie des débats contemporains sur la justification.<ref>Laurence BonJour & Sosa, Ernest, ''Epistemic Justification: Internalism vs. Externalism, Foundations vs. Virtues'', Blackwell, 2003.</ref> ===== Problèmes et tensions de cette analyse ===== En dépit de sa transparence formelle, l’analyse JTB rencontre plusieurs difficultés sérieuses. La première concerne la notion même de justification. Que signifie, de façon précise, « être justifié » ? À partir de quel niveau de soutien rationnel estime-t-on que les raisons sont suffisantes ?<ref>Keith DeRose, « Solving the Skeptical Problem », ''The Philosophical Review'', vol. 104, n° 1, 1995, p. 1-52.</ref> Une croyance peut paraître très bien justifiée au sujet et se révéler néanmoins fausse (si, par exemple, un ami habituellement digne de confiance me trompe, ou si une source réputée sûre se trompe). Il apparaît ainsi que la justification ne garantit pas la vérité : elle peut toujours être remise en cause par de nouvelles informations ; on dit qu’elle est ''défaisable''.<ref>John Pollock, ''Contemporary Theories of Knowledge'', Rowman & Littlefield, 1986, p. 29-35.</ref> La justification doit donc être pensée comme un état révisable, soumis à correction. La seconde difficulté tient à la régression justificative. Pour qu’une croyance soit justifiée, elle semble devoir s’appuyer sur d’autres croyances justifiées. Mais celles-ci renvoient à d’autres encore, et ainsi de suite.<ref>BonJour, Laurence, ''The Structure of Empirical Knowledge'', op. cit., p. 21-32.</ref> On se heurte alors à ce que la tradition désigne sous le nom de ''trilemme d’Agrippa'' : ou bien l’on accepte une régression infinie (chaque croyance reposant sur une autre sans jamais atteindre de fondement ultime, ce qui paraît invivable pour un sujet fini), ou bien l’on admet une circularité (A est justifié par B, qui est justifié par A), ou bien l’on pose l’existence de croyances ''fondamentales'' qui seraient justifiées sans s’appuyer sur d’autres croyances.<ref>Sextus Empiricus, ''Outlines of Pyrrhonism'', trad. R.G. Bury, Harvard University Press, 1933, Livre I, § 165-177.</ref> Ces trois issues correspondent à trois grandes familles de théories : le fondationnalisme (qui admet des croyances de base), le cohérentisme (qui fait dépendre la justification de la cohérence globale du système de croyances) et l’infinitisme (qui assume la régression sans fin).<ref>Michael Huemer, ''Epistemology. Contemporary Readings'', Routledge, 2002, p. 1-50.</ref> Chacune de ces positions rencontre des objections précises, et aucune ne fait l’unanimité.<ref>Keith Lehrer & Cohen, Stewart, « Justification, Truth, and Coherence », ''Synthese'', vol. 55, n° 2, 1983, p. 191-207.</ref> Enfin, la nature même de la croyance et de la justification reste difficile à cerner. Sommes-nous simplement justifiés ou non, ou bien la justification se déploie-t-elle par degrés ? Si l’on admet des degrés de justification, à partir de quel seuil peut-on dire qu’une croyance justifiée constitue une connaissance ?<ref>Jason Stanley, ''Knowledge and Practical Interests'', Oxford University Press, 2005.</ref> La formulation classique du JTB suppose en général des découpages binaires : croire ou ne pas croire, être justifié ou ne pas l’être. Une telle manière de trancher ne rend pas justice à la complexité de nos pratiques effectives de croyance, où interviennent des niveaux de confiance différenciés, des indices de poids inégal et des révisions successives. ===== Pertinence et fécondité persistantes ===== Malgré ces difficultés, l’analyse tripartite demeure au cœur de la réflexion épistémologique. Elle conserve cette place parce qu’elle isole un trait important de notre usage ordinaire du mot « savoir » : nous distinguons spontanément une croyance vraie due au hasard d’un savoir proprement dit, qui suppose à la fois l’adhésion du sujet, la vérité de ce qu’il affirme et l’existence de raisons appropriées.<ref>Timothy Williamson, ''Knowledge and Its Limits'', Oxford University Press, 2000, p. 1-50.</ref> Cette analyse met aussi en évidence la fragilité de la connaissance face au doute sceptique. Si savoir revient à satisfaire ensemble les conditions de vérité, de croyance et de justification, il reste toujours envisageable que nous nous trompions sur l’un ou l’autre de ces aspects : nous pouvons nous méprendre sur les faits, mal évaluer ce que nous croyons réellement, ou surestimer la force de nos raisons.<ref>Peter Unger, ''Ignorance. A Case for Scepticism'', Oxford University Press, 1975.</ref> Dans le cadre du JTB, aucune procédure logique ne met définitivement nos connaissances à l’abri d’une remise en question. Surtout, le schéma JTB a servi de point d’ancrage à une grande part de l’épistémologie récente. Une large série de discussions se déploie à partir de lui : comment préciser la notion de justification ?<ref>Linda Zagzebski, ''Virtues of the Mind: An Inquiry into the Nature of Virtue and the Ethical Foundations of Knowledge'', Cambridge University Press, 1996.</ref> Faut-il la comprendre comme une propriété entièrement interne à la vie mentale du sujet, ou comme un état dépendant aussi de la fiabilité objective de ses mécanismes cognitifs ?<ref>Fred Dretske, ''Knowledge and the Flow of Information'', MIT Press, 1981.</ref> Les trois conditions sont-elles suffisantes, ou doit-on ajouter une quatrième exigence (absence de hasard, fiabilité, lien causal adéquat, etc.) pour éliminer les contre-exemples de type gettierien ?<ref>Robert Nozick, ''Philosophical Explanations'', Harvard University Press, 1981, p. 172-178.</ref> Et l’absence d’une seule de ces trois conditions exclut-elle toujours toute connaissance ? Ces questions ne relèvent pas d’un simple intérêt historique. Elles continuent d’ordonner une grande partie des recherches actuelles, et tant que l’on s’interrogera sur ce que signifie véritablement « savoir », l’analyse tripartite — fût-elle destinée à être corrigée — restera l’un des schémas conceptuels de référence.<ref>Matthias Steup, Turri, John & Sosa, Ernest (dir.), ''Contemporary Debates in Epistemology'', Wiley-Blackwell, 2014.</ref> ==== 1.2 Le problème de Gettier et ses conséquences ==== ===== L’article de 1963 : un tournant conceptuel ===== En 1963, Edmund Gettier publie dans la revue ''Analysis'' un article de trois pages intitulé ''Is Justified True Belief Knowledge ?''<ref>Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, n° 6, 1963, p. 121-123.</ref> Ce texte, très court et d’allure modeste, entraîne pourtant une remise en cause profonde, au sein de l’épistémologie analytique, du schéma tripartite qui avait servi de cadre d’analyse de la connaissance pendant plusieurs décennies. Plus de soixante ans après sa parution, il demeure l’un des articles les plus commentés de la philosophie contemporaine et a donné lieu à une littérature secondaire considérable. La thèse de Gettier est d’une grande simplicité, mais ses effets sont déstabilisants : les trois conditions de vérité, de croyance et de justification ne suffisent pas à définir la connaissance. Il existe des situations dans lesquelles un sujet remplit pleinement ces trois conditions sans pour autant savoir. Ces situations sont devenues familières sous le nom de ''Gettier cases'', ou « cas de type Gettier ».<ref>Pour une synthèse récente des recherches, voir : Ichikawa, Jonathan L. & Steup, Matthias, « The Analysis of Knowledge », dans ''The Stanford Encyclopedia of Philosophy'', 2018.</ref> ===== Deux exemples initiaux de Gettier ===== ''Premier cas : l’emploi et les dix pièces'' Smith et Jones ont tous deux posé leur candidature au même poste. Supposons que : * le président de l’entreprise ait assuré à Smith que Jones serait retenu ; * Smith ait compté les pièces de monnaie dans la poche de Jones et constaté qu’il y en a exactement dix. À partir de ces deux informations, Smith infère, par un raisonnement apparemment irréprochable, la proposition suivante : « la personne qui obtiendra l’emploi a dix pièces dans sa poche ». La conclusion découle logiquement des prémisses, et celles-ci sont, pour Smith, très bien attestées. Il semble donc disposer d’une justification robuste pour cette croyance. Imaginons maintenant que : * contrairement à ce qu’a affirmé le président, ce soit en réalité Smith qui obtienne le poste ; * Smith ait lui-même exactement dix pièces dans sa poche, sans en avoir conscience. La proposition qu’il croit est pourtant vraie : la personne qui obtiendra l’emploi a bien dix pièces dans sa poche. Smith y croit, et il dispose de raisons qui, de son point de vue, la justifient. Toutefois, il est difficile de soutenir qu’il sait que la personne qui aura le poste possède dix pièces : sa croyance rencontre la vérité pour un motif tout à fait différent de celui sur lequel reposait sa justification. La coïncidence entre vérité et justification est ici largement fortuite. ''Deuxième cas : la disjonction fortuite'' Smith a de bonnes raisons de penser que Jones possède une voiture. En s’appuyant sur cette croyance, il infère plusieurs propositions disjonctives, par exemple : * « Jones possède une Ford, ou bien Brown est à Barcelone » ; * « Jones possède une Ford, ou bien Brown est à Brest-Litovsk » ; * « Jones possède une Ford, ou bien Brown est à Prague ». Du point de vue logique, ces inférences disjonctives sont correctes : si « Jones possède une Ford » est vraie, chacune des disjonctions l’est aussi. Smith se trouve donc, semble-t-il, pleinement justifié à accepter chacune de ces propositions. Supposons maintenant que : * Jones ne possède en réalité aucune voiture et ne conduit qu’un véhicule de location ; * par une coïncidence indépendante du raisonnement de Smith, Brown se trouve effectivement à Barcelone. La proposition « Jones possède une Ford, ou bien Brown est à Barcelone » est alors vraie, Smith y croit, et sa croyance lui paraît appuyée sur un raisonnement correct. Pourtant, il ne sait pas que cette proposition est vraie, puisque toute sa justification repose sur la prémisse erronée selon laquelle Jones possède une voiture.<ref>Gettier, op. cit., p. 122.</ref> ===== Nature du problème : le rôle de la chance épistémique ===== Dans ces deux exemples, la croyance vraie du sujet n’est vraie qu’en vertu d’un hasard favorable. Plus précisément, ce qui fait que la croyance est vraie n’est pas ce qui, du point de vue du sujet, la justifie. La vérité de la proposition et la justification dont se prévaut le sujet se trouvent jointes, mais sans relation épistémique pertinente entre elles. On met ainsi au jour une exigence supplémentaire : pour qu’il y ait connaissance, il ne suffit pas que croyance, vérité et justification soient présentes ; il faut encore que l’accès du sujet à la vérité ne dépende pas de la chance. On ne peut pas dire qu’un sujet sait que p lorsqu’il croit une proposition vraie pour des raisons qui, en réalité, n’ont rien à voir avec ce qui rend cette proposition vraie.<ref>Saul Kripke, « A Puzzle About Belief », dans Margalit, Avishai (dir.), ''Meaning and Use'', D. Reidel, 1979, p. 239-283.</ref> Linda Zagzebski, l’une des principales figures de l’épistémologie contemporaine, a mis en lumière une structure commune à un vaste ensemble de cas de type Gettier : la justification de la croyance repose sur au moins une prémisse fausse, tandis que la croyance elle-même se trouve vraie par effet indirect d’un enchaînement causal distinct.<ref>Linda Zagzebski, « Virtue Epistemology », dans Greco, John & Sosa, Ernest (dir.), ''The Blackwell Guide to Epistemology'', Blackwell, 2003, p. 93-113.</ref> La tension entre ce qui soutient la croyance et ce qui la rend vraie est au cœur du malaise épistémique que produisent ces cas. ===== Le cas des fausses granges : une variante instructive ===== Gettier n’avait proposé que deux exemples. D’autres philosophes ont prolongé sa démarche en construisant de nouvelles variantes. L’une des plus célèbres est le ''cas des fausses granges'' (''fake barn case''), introduit dans la littérature par Alvin Goldman et parfois associé à une remarque de Saul Kripke. Le scénario est le suivant. Vous traversez en voiture une région où l’on a érigé de nombreuses « fausses granges » : des façades peintes en forme de grange, qui ne sont pas de véritables bâtiments. Il n’y a qu’une seule grange authentique dans cette région, qui a été récemment repeinte en rouge. Toutes les fausses granges ont une apparence assez semblable à distance. Vous regardez par la fenêtre et, par hasard, votre regard se pose sur la seule grange réelle ; vous formez alors la croyance : « voici une grange ». Peut-on dire que vous savez qu’il y a une grange devant vous ? L’intuition la plus répandue est négative. Votre croyance est vraie, vous disposez d’une justification perceptive tout à fait ordinaire, mais vous vous trouvez dans un environnement trompeur : si votre regard s’était porté sur l’une des nombreuses façades, vous auriez formé la même croyance, qui aurait alors été fausse. Votre accès à la vérité dépend ici de la configuration accidentelle de la situation. Ce cas souligne une dimension que les exemples de Gettier ne faisaient qu’esquisser : il ne suffit pas de considérer les raisons internes du sujet ; la structure de l’environnement épistémique importe aussi. Vous ignorez que la région est saturée de fausses granges – ignorance qui, si elle était levée, vous conduirait à suspendre votre jugement. Une information contextuelle cruciale manque à votre justification.<ref>Alvin Goldman, « Discrimination and Perceptual Knowledge », ''The Journal of Philosophy'', vol. 73, n° 20, 1976, p. 771-791.</ref> ===== Conséquences théoriques : la recherche d’une condition supplémentaire ===== Le problème de Gettier a conduit les épistémologues à modifier le schéma tripartite plutôt qu’à l’abandonner purement et simplement. Si les trois conditions ne suffisent pas, quelle exigence supplémentaire faut-il introduire ? Une première famille de réponses est regroupée sous l’étiquette ''No False Lemmas''. L’idée, dans l’une de ses versions, est qu’une croyance vraie justifiée ne constitue une connaissance que si elle ne dépend pas, dans son argumentation essentielle, de prémisses fausses. Dans les cas de Gettier, la croyance de Smith serait ainsi disqualifiée, parce que son raisonnement s’appuie, de manière décisive, sur une croyance erronée. Reste à préciser ce qu’il faut entendre par « dépendre » : toute prémisse fausse intervenant à quelque niveau que ce soit invalide-t-elle la justification, ou seulement les prémisses fausses qui jouent un rôle central dans l’argument ?<ref>Keith Lehrer & Thomas Paxton, « Knowledge, Undefeated Justified True Belief », ''The Journal of Philosophy'', vol. 66, n° 8, 1969, p. 225-237.</ref> Une seconde stratégie est l’''approche causale'' d’Alvin Goldman : une croyance vraie constitue une connaissance si, et seulement si, elle est reliée de façon causale appropriée au fait qui la rend vraie. Dans le premier cas de Gettier, la croyance de Smith n’est pas produite par le fait que lui-même possède dix pièces ; elle résulte d’un enchaînement causal qui passe par une information fausse concernant Jones. La croyance n’est donc pas reliée comme il faut à la réalité. Cependant, cette approche se heurte à des cas comme celui des fausses granges, où la croyance perceptive est bien causée par la grange réelle, mais où l’environnement rend malgré tout douteux le statut de connaissance.<ref>Goldman, Alvin, « A Causal Theory of Knowing », ''The Journal of Philosophy'', vol. 64, n° 12, 1967, p. 357-372.</ref> Une troisième ligne de réponse est le ''modèle du tracking'' proposé par Robert Nozick. Pour qu’un sujet sache que p, il ne suffit pas qu’il ait une croyance vraie justifiée ; il faut encore que sa croyance « suive » la vérité à travers des situations proches. Nozick formule cela ainsi : si p était faux, le sujet ne croirait pas que p. Dans le cas des fausses granges, cette condition n’est pas satisfaite : dans des mondes voisins où vous regardez une façade, vous croiriez tout de même qu’il y a une grange. Votre croyance ne varie pas de façon adéquate avec la vérité.<ref>Robert Nozick, ''Philosophical Explanations'', Harvard University Press, 1981, p. 172-178.</ref> Aucune de ces propositions ne fait consensus. Chacune éclaire une dimension réelle du phénomène, mais se heurte à son tour à des contre-exemples. Le problème mis en évidence par Gettier apparaît ainsi comme remarquablement résistant.<ref>Duncan Pritchard, ''Epistemic Luck'', Oxford University Press, 2005.</ref> ===== L’impact épistémologique : un champ reconfiguré ===== L’effet du problème de Gettier ne se limite pas à l’ajout d’une difficulté ponctuelle. Il a contribué à redessiner l’ensemble du champ épistémologique. D’abord, il a montré que la notion de connaissance ne peut pas être traitée comme un simple objet de définition terminologique. La question « qu’est-ce que connaître ? » exige une enquête fine sur les situations concrètes dans lesquelles nous accordons ou refusons le statut de savoir. L’ampleur de la littérature consacrée aux cas de type Gettier témoigne de ce déplacement : la réflexion se concentre sur la structure des exemples et sur la manière dont nos jugements réagissent à leurs variations. Ensuite, ces discussions ont souligné que l’analyse conceptuelle doit être confrontée à des contre-exemples construits avec soin. Il ne suffit pas de proposer une définition a priori de la connaissance ; il faut examiner systématiquement si cette définition résiste à des cas imaginaires qui la mettent à l’épreuve.<ref>Frank Jackson, « Gettier Cases as Counterexamples to the Justified True Belief Analysis of Knowledge », dans Pappas, George S. & Swain, Marshall (dir.), ''Essays on Knowledge and Justification'', Cornell University Press, 1978, p. 25-37.</ref> Enfin, le problème de Gettier a encouragé plusieurs réorientations majeures : certains ont renoncé à l’espoir de formuler une analyse nécessaire et suffisante de la connaissance ; d’autres ont privilégié l’épistémologie des vertus, les théories de type ''tracking'', diverses formes d’externalisme ou des approches contextualistes. Ces courants ont en commun de prendre au sérieux les limites du modèle tripartite et de chercher à mieux intégrer la dimension du hasard épistémique.<ref>Matthias Steup, « Epistemology », dans ''Stanford Encyclopedia of Philosophy'', 2021.</ref> ===== Débat actuel : portée et légitimité du problème ===== On pourrait penser que, après plusieurs décennies de travail, le problème de Gettier a trouvé une solution stabilisée. Il n’en est rien. Une partie de la discussion contemporaine porte même sur la légitimité des intuitions qui soutiennent les jugements initiaux sur ces cas. Duncan Pritchard, notamment, a développé une ''épistémologie anti-chance'' qui insiste sur l’idée que la connaissance exclut une certaine forme de hasard défavorable (''epistemic luck'') susceptible de priver un sujet de la maîtrise de ses croyances. Tim Williamson, de son côté, a proposé que la connaissance soit prise comme notion primitive, irréductible à la combinaison d’une croyance et de conditions supplémentaires : la structure même du schéma JTB, centré sur la croyance, pourrait alors être inadaptée pour saisir ce qu’est savoir.<ref>Tim Williamson, ''Knowledge and Its Limits'', Oxford University Press, 2000, p. 34-73.</ref> Parallèlement, des travaux en psychologie cognitive ont mis en évidence des variations significatives dans les jugements portés sur les cas de type Gettier selon les contextes culturels ou les groupes de sujets. Certains y ont vu une raison de s’interroger sur la stabilité et la fiabilité de nos intuitions ordinaires concernant la connaissance : peuvent-elles encore servir de critère pour départager les théories ?<ref>Jonathan Weinberg, Shaun Stich & David E. Cohen, « Individually Individuated Concepts », ''Journal of Philosophy'', vol. 99, n° 3, 2002, p. 109-126.</ref> Malgré ces interrogations, plusieurs points de convergence apparaissent : (1) l’article de Gettier met effectivement en lumière une insuffisance du schéma « croyance vraie justifiée » ; (2) les cas qu’il propose révèlent une dimension essentielle de la connaissance, à savoir la manière dont elle doit écarter certains effets du hasard ; (3) toute théorie contemporaine de la connaissance doit, d’une manière ou d’une autre, expliquer ce qui se passe dans les situations de type Gettier, même si elle choisit de reformuler le problème ou de contester certaines intuitions.<ref>Ichikawa & Steup, op. cit.</ref> À ce titre, le texte de 1963 conserve aujourd’hui encore une influence structurante. Il continue d’alimenter des désaccords substantiels, mais c’est précisément parce qu’il touche à des questions centrales sur le rapport entre justification, vérité et chance dans la connaissance. ==== 1.3 Réponses au problème de Gettier ==== ===== Introduction : la diversité des stratégies ===== Depuis 1963, les épistémologues ont proposé des réponses nombreuses et divergentes au problème de Gettier. Ces réponses ne se laissent pas organiser selon un principe unique. Certaines cherchent à adjoindre une quatrième condition aux trois conditions classiques. D'autres réexaminent et redéfinissent ces trois conditions elles-mêmes. D'autres enfin contestent l'hypothèse même selon laquelle la connaissance devrait faire l'objet d'une analyse définitionnelle en termes de conditions nécessaires et suffisantes. Cette pluralité témoigne de la profondeur du problème : aucun consensus ne s'est imposé sur la manière la plus adéquate de le traiter.<ref>Matthias Steup, Turri, John & Sosa, Ernest (dir.), ''Contemporary Debates in Epistemology'', Wiley-Blackwell, 2014.</ref> ===== La stratégie des conditions supplémentaires ===== '''L'approche par les défaiteurs (Lehrer, Pollock)''' Une première réponse à Gettier s'appuie sur l'idée que la justification doit être ''non défaite'' : elle doit demeurer intacte face aux informations susceptibles de l'annuler ou de l'affaiblir. On appelle ''défaiteur'' une proposition vraie qui, si le sujet en prenait connaissance, anéantirait ou affaiblirait de façon décisive la justification de sa croyance initiale.<ref>Keith Lehrer & Thomas D. Paxson, Jr., « Knowledge, Undefeated Justified True Belief », ''The Journal of Philosophy'', vol. 66, n° 8, 1969, p. 225-237.</ref> Considérons d'abord ce qu'est un défaiteur de manière abstraite. Supposons que vous êtes justifié de croire une proposition P sur la base d'un ensemble de prémisses. Un défaiteur pour votre justification est une proposition Q (vraie) qui possède cette propriété : si vous la croyiez, cet ajout suffirait à annuler ou à gravement affaiblir votre justification de P. En d'autres termes, Q est incompatible avec le maintien de votre justification antérieure. Dans l'exemple classique de Smith et Jones, considérons les différents défaiteurs potentiels : 1. Un défaiteur de premier ordre serait : « le président a trompé Smith : Jones n'obtiendra pas l'emploi ». Si Smith savait cela, il ne pourrait plus légitimement soutenir que la personne qui obtiendra l'emploi possède dix pièces dans sa poche, puisque sa conclusion reposait sur la prémisse que Jones obtiendrait le poste. 2. Mais il existe aussi un défaiteur de second ordre, que Lehrer appelle un ''défaiteur du défaiteur'' : c'est une proposition vraie qui, bien que rendant fausse la croyance du sujet, demeurerait ignorée du sujet. Par exemple : « Smith possède lui-même dix pièces dans sa poche ». Cette proposition est vraie, mais son existence ne suffit pas à détruire la justification initiale de Smith pour croire que la personne qui obtiendra l'emploi possède dix pièces. C'est précisément sur ce point que la théorie des défaiteurs se complexifie. Lehrer et Paxson proposent une distinction entre les ''défaiteurs'' proprement dits (qui annulent la justification si le sujet en prenait connaissance) et les ''propositions qui rendent fausse la croyance'' (qui peuvent être vraies sans pour autant détruire la justification). L'idée motrice est la suivante : pour qu'une croyance vraie et justifiée constitue une connaissance, il ne suffit pas qu'elle soit vraie, justifiée, et qu'aucun défaiteur inconnu du sujet ne la rende inexplicablement vraie. Il faut également qu'il n'existe pas de défaiteur vrai de la justification : en d'autres termes, toute information qui annulerait la justification doit être connue du sujet ou intégrée à son système de croyances de manière appropriée.<ref>Keith Lehrer, ''Theory of Knowledge'', Westview Press, 2e édition, 1990, p. 109-135.</ref> Cette approche possède un attrait intuitif considérable. Elle rend compte de la raison pour laquelle, dans les cas de Gettier, le sujet n'a pas de connaissance : sa justification est vulnérable à une information vraie dont il ignore l'existence. En l'absence d'information qui annulerait sa justification, il pourrait affirmer connaître ; mais du moment que cette information existe (même s'il l'ignore), son statut épistémique en est compromis. Cependant, l'approche par les défaiteurs se heurte à plusieurs difficultés sérieuses, qui ont alimenté un large corpus de critiques. Premièrement, la question de l'identification des défaiteurs. Comment déterminer avec précision quelles propositions doivent être comptées comme de véritables défaiteurs ? Faut-il considérer toute proposition vraie qui pourrait, en principe, annuler la justification ? Une telle condition serait excessivement stricte. Imaginez que vous êtes justifié de croire que « Marie viendra à la réunion » parce qu'elle vous l'a promise. Une infinité de propositions vraies « annulerait » cette justification en un sens : « Marie a changé d'avis », « Marie a eu un accident », « Marie a reçu un appel urgent », et ainsi de suite. Faudrait-il que vous ignoriez chacune de ces propositions pour que votre croyance constituât une connaissance ? Deuxièmement, il se pose la question de la ''pertinence'' des défaiteurs. Faut-il retenir que les défaiteurs pertinents, c'est-à-dire ceux qui ont un lien sémantique ou logique direct avec la croyance et sa justification ? Mais selon quels critères établir cette pertinence ? La pertinence est-elle une notion objective ou relative au contexte ? Lehrer lui-même a reconnu cette difficulté et a proposé diverses reformulations, cherchant à préciser ce qui distingue un défaiteur ''effectivement pertinent'' d'une proposition qui, bien que vraie et capable d'annuler la justification en un sens large, n'a aucune pertinence épistémique réelle. Troisièmement, il existe une tension entre deux conceptions de la justification chez les tenants de cette approche. Certains soutiennent que la justification est intrinsèquement liée à ce que le sujet connaît ou croit : c'est une notion ''internaliste'', qui ne dépend que des états mentaux du sujet. D'autres affirment que la justification dépend aussi de faits externes, notamment de l'existence de défaiteurs dans le monde réel. Cette seconde conception rend la justification dépendante de l'environnement, ce qui transforme l'approche en une forme d'externalisme. Quatrièmement, les critiques ont soulevé le problème de la ''régression infinie des défaiteurs''. Si l'absence d'un défaiteur vrai est requise pour la connaissance, comment éviter une régression ? Car pour tout défaiteur Q qui pourrait annuler une justification, on peut imaginer un défaiteur du défaiteur (une proposition R qui, si elle était vraie et connue, annulerait l'effet annulant de Q). Cette régression potentiellement infinie semble rendre la condition impraticable.<ref>Robert K. Shope, ''The Analysis of Knowing: A Decade of Research'', Princeton University Press, 1983, p. 87-104.</ref> Enfin, l'approche par les défaiteurs a été critiquée pour son incapacité à traiter certains cas complexes. Considérez le cas des fausses granges : vous voyez une grange réelle dans une région remplie de façades de granges. Quel est le défaiteur pertinent ? Est-ce simplement « cette région contient de nombreuses fausses granges » ? Mais vous pouvez voir la grange effectivement, et votre justification perceptive directe semble robuste. Le défaiteur « il existe d'autres fausses granges ailleurs » ne paraît pas logiquement connecté à votre justification de manière évidente. Cela suggère que la notion de défaiteur elle-même peut manquer de clarté dans des contextes non standard. Malgré ces difficultés, l'approche par les défaiteurs a exercé une influence durable sur la théorie de la connaissance. Elle a inspiré d'autres formulations, notamment la théorie de la ''défaisabilité'' en général, selon laquelle une croyance justifiée ne constitue une connaissance que si elle n'est pas susceptible d'être défaite par l'acquisition d'informations nouvelles. Et elle a mis en lumière l'idée que l'absence d'informations pertinentes qui invalideraient la justification joue un rôle crucial dans la détermination du statut épistémique d'une croyance. '''La condition de sécurité (Sosa)''' Ernest Sosa a proposé, en alternative à la condition de ''suivi'' de Nozick, une condition de ''sécurité''. Cette proposition émerge d'une réflexion critique sur les insuffisances de l'approche de Nozick et offre une caractérisation nouvelle de ce qui distingue la connaissance de la simple croyance vraie justifiée.<ref>Ernest Sosa, ''Knowledge in Perspective'', Cambridge University Press, 1991, p. 138-147.</ref> Pour bien comprendre la condition de sécurité, il convient d'abord de l'opposer à la condition de sensitivité proposée par Robert Nozick. La ''sensitivité'' exige que, si la proposition était fausse, le sujet ne la croirait pas. Formulée en termes modaux : nécessairement, si P était faux, S ne croirait pas que P. Autrement dit, la croyance du sujet « suit » ou « épouse » la vérité de la proposition : sa croyance varie en fonction de la vérité de ce qu'elle porte sur. La ''sécurité'', par contraste, exige quelque chose de différent : qu'il ne soit pas ''facilement possible'' que le sujet croie cette proposition alors qu'elle serait fausse. Ou, formulé positivement : dans tous les mondes possibles suffisamment proches du monde actuel, où le sujet emploie la même méthode pour former sa croyance, cette croyance demeure vraie. La sécurité concerne donc non pas la sensitivité à la fausseté contrefactuelle, mais plutôt la robustesse de la méthode de formation de croyance dans les circonstances qui ressemblent à celle où le sujet se trouve actuellement. Pour illustrer cette distinction, considérons le cas des fausses granges. Vous voyez une vraie grange dans une région remplie de façades. Votre croyance « c'est une grange » est vraie, et elle provient de la perception visuelle, qui est une méthode ordinairement fiable. Appliquons les deux conditions : La ''sensitivité'' : Si cette structure n'était pas une vraie grange (si c'était une façade), ne la croiriez-vous pas ? Réponse : probablement si. Vous seriez trompé par l'apparence, tout comme vous l'auriez été si vous aviez regardé une autre façade. Votre croyance n'est donc ''pas sensitive'' à la fausseté : elle aurait pu être fausse sans que vous le sentiez. La sensitivité échoue donc dans ce cas. La ''sécurité'' : Dans tous les mondes voisins où vous employez la même méthode (la perception visuelle) et où vous regardez une structure dans cette région, cette structure est-elle une vraie grange ? Non : dans beaucoup de mondes voisins, vous apercevriez une façade, et votre croyance serait fausse. La sécurité échoue aussi. Cependant, considérons maintenant un cas différent : vous voyez votre ami Pierre assis à côté de vous dans une pièce bien éclairée. Votre croyance « Pierre est assis à côté de moi » est vraie et provient de la perception directe. La ''sensitivité'' : Si Pierre n'était pas réellement là, ne le croiriez-vous pas ? Il est hautement probable que non : les circonstances sont normales, votre perception est directe et claire. La sensitivité réussit donc ici. La ''sécurité'' : Dans tous les mondes voisins où vous employez la perception dans les mêmes conditions, Pierre est-il assis à côté de vous ? Oui, en règle générale : les mondes voisins où vous verriez quelqu'un assis à côté de vous dans ces circonstances normales sont des mondes où c'est effectivement Pierre. La sécurité réussit donc aussi. Mais voici où la distinction devient philosophiquement cruciale. Considérez un cas d'illusion systématique : vous êtes dans un simulateur neuronal parfait, et on vous montre l'illusion d'une grange. Vous croyez « c'est une grange ». La ''sensitivité'' : Si ce n'était pas une grange (ce qu'il n'est pas, puisque c'est une illusion), ne le croiriez-vous pas ? Malheureusement si : le simulateur continuerait à vous montrer exactement la même image. La sensitivité échoue. La ''sécurité'' : Dans tous les mondes voisins où vous percevez une structure ressemblant exactement à une grange dans les mêmes conditions sensorielles internes, est-ce réellement une grange ? Non, probablement pas : vous pourriez être illusionné. Mais Sosa argurait que si l'on considère les mondes véritablement proches en termes de circonstances réelles, alors dans le monde actuel où vous êtes dans un simulateur, les mondes voisins sont aussi des mondes de simulateur, et votre croyance y demeure vraie (il y a une grange dans votre expérience simulée). La sécurité pourrait donc réussir, selon certaines formulations. C'est précisément la raison pour laquelle Sosa préfère la sécurité à la sensitivité. Il argue que la sensitivité ne capture pas ce que nous cherchons vraiment à préserver dans notre notion de connaissance. Nous voulons que la croyance soit formée de telle sorte qu'elle soit ''sûre'', c'est-à-dire qu'elle ne puisse pas facilement être fausse étant donné la méthode employée. Nous ne cherchons pas simplement à exclure la fausseté contrefactuelle globale. Mais la distinction entre sensitivité et sécurité est subtile, et les deux conditions peuvent entrer en conflit ou converger selon les cas considérés. Considérons le cas d'un ''faux banc''. Vous êtes dans un musée d'art moderne où certaines œuvres d'art sont des reproductions si convaincantes qu'elles sont indiscernables des originaux. Vous voyez un banc en bois massif et formez la croyance « c'est un banc ». Supposons que c'est un ''faux banc'' artistique, une sculpture si réaliste qu'elle ressemble exactement à un banc ordinaire, mais qui n'est pas réellement un banc (c'est une œuvre d'art abstraite). La ''sensitivité'' échoue clairement : vous ne sauriez percevoir la différence, donc si c'était vraiment une fausse sculpture, vous y croiriez quand même. La ''sécurité'' pose une question plus complexe : si vous employez la même méthode perceptive (la vision) dans les circonstances similaires du musée, obtenez-vous une croyance sûre ? Cela dépend de comment on modélise les « mondes voisins ». Si les mondes voisins incluent d'autres faux bancs dans le musée, votre croyance pourrait être fausse. Mais si les mondes voisins sont suffisamment restreints aux seuls cas où vous percevez exactement la même chose, la croyance demeure vraie dans ces mondes. Cette ambiguïté révèle une tension fondamentale : la condition de sécurité, tout comme celle de sensitivité, dépend de la manière dont on caractérise les ''mondes possibles proches''. Faut-il les définir en termes d'apparence sensorielle ? En termes de faits environnementaux ? En termes de fiabilité des processus cognitifs ? Selon le choix qu'on fait, la sécurité peut être satisfaite ou non. Sosa défend néanmoins l'idée que la sécurité rend mieux compte que la sensitivité de nos intuitions ordinaires sur plusieurs points décisifs. Premièrement, dans le cas du scepticisme radical (simulateur neuronal parfait), la sécurité permet de dire que nous ''ne savons pas'' que nous ne sommes pas dans le simulateur, car il n'est pas sûr que nous ne le soyons pas — mais cela n'invalide pas notre connaissance ordinaire du monde tel que nous le vivons. Deuxièmement, la sécurité capture mieux l'idée que la connaissance requiert une certaine ''stabilité'' ou ''fiabilité'' de la méthode : tant que la méthode est sûre dans le contexte où elle s'exerce, la croyance peut compter comme connaissance.<ref>Ernest Sosa, ''A Virtue Epistemology: Apt Belief and Reflective Knowledge'', Oxford University Press, 2007, vol. 1, p. 84-101.</ref> Cependant, la condition de sécurité a aussi suscité des critiques sérieuses. Certains ont soutenu qu'elle est trop permissive : elle semble permettre des cas où l'on ne voudrait pas dire qu'il y a connaissance. D'autres ont argumenté qu'elle est trop restrictive dans d'autres contextes. En particulier, la dépendance de la sécurité envers la notion de ''mondes proches'' rend la condition vulnérable aux mêmes difficultés que la sensitivité : la notion même de proximité modale reste contestée et ambiguë.<ref>John Greco, « Sosa's Virtue Epistemology and the Problem of Modal Luck », dans ''Contemporary Debates in Epistemology'', Wiley-Blackwell, 2014, p. 227-239.</ref> Malgré ces difficultés, la condition de sécurité demeure une contribution importante à la théorie de la connaissance post-gettierienne. Elle a inspiré d'autres approches, notamment l'épistémologie anti-hasard de Duncan Pritchard, qui intègre l'idée de sécurité dans une théorie plus large de l'exclusion du hasard épistémique. Et elle continue de structurer les débats contemporains sur ce qui distingue la connaissance de la simple croyance vraie justifiée. ===== Internalismes et externalismes ===== '''La ligne de partage fondamentale''' Une autre manière de répondre à Gettier consiste à distinguer selon que la justification relève uniquement de facteurs internes au sujet ou dépend aussi de facteurs externes. L''''internalisme''' soutient que seuls des éléments internes au sujet — ses états mentaux, ses croyances, ses expériences conscientes — déterminent si une croyance est justifiée. Dans une version stricte, l'internalisme affirme que deux sujets ayant des états mentaux identiques disposent du même degré de justification pour leurs croyances respectives. L''''externalisme''' refuse cette limitation. Pour l'externaliste, la justification dépend également de faits externes : la fiabilité effective des processus de formation des croyances, les relations causales appropriées entre le sujet et le monde, ou encore des caractéristiques objectives de l'environnement cognitif.<ref>William Alston, ''Epistemic Justification. Essays in the Theory of Knowledge'', Cornell University Press, 1989, p. 227-245.</ref> '''Application au problème de Gettier''' Les internalistes ont tendance à soutenir que, dans les cas de Gettier, Smith ne dispose pas, en réalité, d'une justification pleinement suffisante : même si ses prémisses lui paraissent solidement établies et si son raisonnement est valide, il lui manque, du point de vue interne, un élément qui distinguerait une véritable justification d'une simple apparence de justification. Les externalistes, à l'inverse, peuvent admettre que Smith possède une justification interne satisfaisante au sens internaliste, mais affirmer qu'une condition externe fait défaut : sa croyance ne s'enracine pas de manière adéquate dans le fait qui la rend vraie, ou elle n'est pas produite par une faculté cognitive effectivement fiable dans la situation considérée.<ref>Fred Dretske, ''Seeing and Knowing'', University of Chicago Press, 1969.</ref> ===== L'approche par la fiabilité (fiabilisme) ===== Le ''fiabilisme'' d'Alvin Goldman propose une reformulation nette de la justification : une croyance est justifiée si, et seulement si, elle résulte d'un processus de formation des croyances ''fiable'', c'est-à-dire d'un processus qui, en règle générale, produit des croyances vraies plutôt que des croyances fausses. Dans les cas de Gettier, Smith emploie bien un certain type d'inférence déductive, qui s'avère généralement fiable lorsque les prémisses sont vraies. Mais, dans son cas, l'une des prémisses est fausse. Si l'on décrit le processus de manière plus fine — par exemple : « tirer une conclusion à partir d'un ensemble de prémisses parmi lesquelles figure une fausse croyance constitutive » — ce processus n'est plus fiable ; la croyance de Smith n'est vraie qu'accidentellement. Le fiabiliste en conclut que Smith ne sait pas, bien que sa croyance soit vraie et justifiée au sens ordinaire. L'avantage du fiabilisme tient à sa simplicité : il propose un principe unique pour rendre compte du fait que les cas de Gettier ne donnent pas lieu à la connaissance. Son point faible réside dans la difficulté de caractériser avec précision les processus de formation des croyances : à quel niveau de généralité faut-il les décrire ? Un processus formulé de manière très générale (par exemple « perception visuelle ») peut être globalement fiable, alors que ce même processus décrit de façon plus spécifique (« perception visuelle dans une région remplie de fausses granges ») cessera de l'être.<ref>Alvin Goldman, ''Epistemology and Cognition'', Harvard University Press, 1986, p. 93-112.</ref> ===== L'épistémologie des vertus ===== ====== Le tournant anthropologique en épistémologie ====== L'épistémologie des vertus, formulée systématiquement par Linda Zagzebski et Ernest Sosa à partir des années 1980, mais préfigurée dans les travaux antérieurs de Philippa Foot et d'Alasdair MacIntyre, opère un déplacement paradigmatique fondamental au sein de la théorie de la connaissance. Plutôt que de poursuivre la stratégie dominante consistant à adjoindre des conditions formelles supplémentaires à la tripartition classique (vérité, croyance, justification), l'épistémologie des vertus propose une refonte catégorique du questionnement épistémologique lui-même. Elle déplace l'accent de la structure logique de la croyance vers le caractère et les excellences cognitives du sujet connaissant.<ref>Linda Zagzebski, ''Virtues of the Mind: An Inquiry into the Nature of Virtue and the Ethical Foundations of Knowledge'', Cambridge University Press, 1996, p. 271-290.</ref> Ce changement de perspective s'enracine dans une critique profonde de l'approche analytique traditionnelle, laquelle aurait restreint la problématique épistémologique à des questions d'analyse conceptuelle, de conditions nécessaires et suffisantes, au détriment d'une compréhension plus riche et plus existentiellement significative de ce que signifie ''vraiment'' connaître. L'épistémologie des vertus réhabilite l'intuition antique — présente notamment dans la ''phronesis'' aristotélicienne — que la connaissance n'est pas une possession abstraite de vérités, mais une réalisation humaine, un accomplissement du sujet qui s'exerce et se cultive. ====== La conception zagzebskienne : la connaissance comme acte vertueux ====== Linda Zagzebski développe sa théorie autour de l'idée directrice suivante : la connaissance doit être analysée non comme un état doxastique satisfaisant à certaines conditions, mais comme ''un acte de vertu intellectuelle''. Cette réorientation implique une transformation radicale du cadre analytique. '''Redéfinition de la justification épistémique''' Dans la conception zagzebskienne, la ''justification'' d'une croyance ne réside plus dans un ensemble de preuves ou de raisons objectivement disponibles, mais dans le ''caractère vertueux'' du processus cognitif qui a produit la croyance. Une croyance est justifiée, au sens de Zagzebski, lorsqu'elle procède de l'exercice d'une vertu intellectuelle — c'est-à-dire d'une disposition fiable et bien-orientée à bien user de ses facultés cognitives en vue de la vérité. Cette conception introduit une asymétrie significative par rapport aux théories standards de la justification. Tandis que la théorie traditionnelle s'intéresse principalement à la ''structure logique'' de la justification (relations d'appui entre croyances, cohérence systémique, etc.), Zagzebski s'intéresse à la ''qualité morale'' du sujet connaissant. La question n'est plus : « Quelles conditions formelles la croyance doit-elle satisfaire ? », mais plutôt : « Quelles excellences cognitives le sujet a-t-il exercées pour parvenir à cette croyance ? » '''Les vertus intellectuelles comme dispositions de caractère''' Zagzebski établit une distinction fondamentale entre les ''vertus intellectuelles'' et les simples ''capacités cognitives''. La mémoire, la perception, l'attention — ce sont des capacités naturelles que tous les humains possèdent à des degrés variables. Mais les ''vertus intellectuelles'' vont bien au-delà. Ce sont des ''excellences de caractère'', c'est-à-dire des dispositions stables et cultivées qui reflètent une manière d'être, une orientation profonde de l'agent vers la vérité et vers la compréhension. Zagzebski énumère et analyse plusieurs vertus intellectuelles majeures : * L'''humilité épistémique'' : la capacité à reconnaître les limites de son propre savoir, à admettre son faillibilité, à ne pas prétendre à une omniscience. Une personne intellectuellement humble ne surestime pas la portée de ses connaissances ; elle demeure consciente de la possibilité qu'elle se trompe. * L'''ouverture d'esprit'' : la disposition à considérer sérieusement des perspectives divergentes, à résister à la fermeture dogmatique, à accueillir les défis à ses convictions établies sans hostilité préalable. * Le ''courage intellectuel'' : la volonté d'explorer des questions difficiles malgré le risque de se tromper ou de rencontrer des résistances sociales. Le courage intellectuel s'oppose à la lâcheté cognitive — cette tendance à éviter les questions inconfortables ou à accepter des réponses faciles. * La ''persévérance dans l'enquête'' : la constance et la détermination dans la poursuite de la compréhension, même lorsque les obstacles sont considérables et que les résultats demeurent incertains. Cette vertu s'oppose à l'impulsivité et à l'abandon prématuré. * La ''vigilance critique'' : l'attention soutenue au screening des mauvais raisonnements, à la détection des sophismes et des biais, à l'évaluation rigoureuse des preuves. * L'''intégrité intellectuelle'' ou ''honnêteté'' : le refus de la malhonnêteté cognitive, c'est-à-dire la volonté de ne pas manipuler les preuves, de ne pas ignorer délibérément les considérations pertinentes, de rapporter fidèlement ce qu'on découvre. Ces vertus ne sont pas des capacités naturelles avec lesquelles on naît. Ce sont des dispositions qu'on ''cultive'', qu'on ''exerce'', qui se renforcent par la pratique répétée. Tout comme le courage moral ou la générosité, les vertus intellectuelles s'acquièrent par l'habitude, par l'apprentissage, par un engagement prolongé envers l'excellence cognitive. '''La structure formelle de la définition zagzebskienne''' Zagzebski propose une définition analytique de la connaissance qui prend la forme suivante : ''S connaît que P si et seulement si la croyance vraie de S que P procède d'un exercice approprié d'une (ou plusieurs) vertus intellectuelle(s)''.<ref>Linda Zagzebski, op. cit., p. 281-290.</ref> Cette formulation repose sur trois éléments interdépendants : # ''La croyance de S que P'' — l'état doxastique du sujet # ''La vérité de P'' — la conformité de la croyance à la réalité # ''L'exercice approprié d'une vertu intellectuelle'' — le processus cognitif vertueux qui a généré la croyance L'innovation majeure réside dans le troisième élément. Tandis que les théories traditionnelles invoquent la ''justification'' comme condition de la connaissance (mais sans spécifier précisément en quoi elle consiste), Zagzebski propose de remplacer la justification par la ''vertu''. Ce remplacement n'est pas purement verbal ; il induit une transformation conceptuelle profonde. La vertu n'est pas simplement une ''raison'' parmi d'autres pour croire P. C'est une excellente manière d'être, un engagement du sujet envers les normes épistémiques appropriées. ====== La conception sosienne : l'aptitude et la compétence ====== Ernest Sosa développe une approche parallèle mais distincte, qui met l'accent sur la notion d'''aptitude'' (''aptness'') et de ''compétence'' cognitive. Pour Sosa, la connaissance est une ''croyance vraie formée avec aptitude'' — c'est-à-dire une croyance qui est vraie en vertu de la compétence qui l'a produite, et non par simple coïncidence. '''La compétence intellectuelle comme vertu''' Sosa conçoit la ''compétence'' intellectuelle de manière analogue à une compétence physique ou artistique. Tout comme un musicien talentueux exécute une partition de manière apte — c'est-à-dire excellente et appropriée à la tâche — un sujet épistémiquement compétent forme ses croyances de manière apte. L'appréciation de la compétence implique une référence à une norme d'excellence, à un étalon de bonne exécution. La compétence intellectuelle, chez Sosa, n'est pas simplement une capacité mécanique. C'est une ''excellence de performance'' : la capacité à former des croyances vraies de manière fiable et répétée, dans une gamme appropriée de circonstances. Cette excellence repose sur une intériorisation des standards épistémiques pertinents et sur une sensibilité aux conditions qui favorisent ou entravent l'accès à la vérité. '''Distinction entre le bonheur épistémique et l'accomplissement apte''' Une distinction cruciale chez Sosa sépare ce qu'il appelle le ''succès'' (ou le ''bonheur'') épistémique de l'''accomplissement apte''.<ref>Ernest Sosa, ''Virtue Epistemology: Apt Belief and Reflective Knowledge'', Oxford University Press, 2007, vol. 1, p. 25-40.</ref> Le ''succès épistémique'' consiste simplement à avoir une croyance vraie. C'est un résultat favorable, une coïncidence heureuse. Un sujet peut avoir du succès épistémique — sa croyance peut être vraie — sans que ce succès procède de sa compétence. C'est le cas paradigmatique dans les exemples de Gettier. L'''accomplissement apte'', par contraste, se produit lorsque le succès (la vérité de la croyance) est ''causé de manière appropriée'' par l'exercice de la compétence du sujet. L'apte accomplissement constitue une forme d'excellence : ce n'est pas seulement qu'un but soit atteint, mais qu'il soit atteint ''bien'', ''excellemment'', ''de manière à refléter les compétences du sujet''. La connaissance, selon Sosa, est précisément cet accomplissement apte : une croyance vraie qui procède d'une compétence exercée de manière appropriée dans les circonstances. ====== Application aux cas de Gettier ====== L'épistémologie des vertus offre une réponse élégante et unifiée au problème de Gettier. Considérons à nouveau le cas de Smith et Jones. Smith raisonne correctement sur le plan formel — son inférence obéit aux règles de la logique. Mais son raisonnement repose sur une croyance fausse, une prémisse qu'il n'a pas soumise à la critique appropriée. En d'autres termes, Smith n'a pas exercé la ''vigilance critique'' ou l'''humilité épistémique'' qui caractérisent les vertus intellectuelles. Il a accepté l'affirmation du président sans la mettre suffisamment en question ; il a pris pour acquis que son inférence était solide sans exécuter la diligence cognitive requise. De ce point de vue, le défaut dans la situation de Smith n'est pas d'ordre formel ou structural — ce n'est pas qu'une condition logique fait défaut. C'est que Smith n'a pas exercé les excellences intellectuelles appropriées. Sa croyance vraie n'est pas le fruit de sa vertu, mais le fruit du hasard. Elle résulte d'une coïncidence fortuite (la présence de dix pièces dans sa propre poche) qui neutralise l'inadéquation initiale de sa justification. Une personne qui exercerait véritablement les vertus intellectuelles — qui serait humble, critique, vigilante, consciencieuse — ne se trouverait pas aisément dans une situation de type Gettier. Elle examinerait de près les prémisses ; elle serait consciente de la faillibilité des sources (même du président) ; elle résisterait à la tentation de conclure trop rapidement. ====== Avantages et enjeux de l'approche vertueuse ====== '''Avantages philosophiques''' L'épistémologie des vertus présente plusieurs avantages significatifs. Premièrement, elle restaure une connexion importante entre épistémologie et éthique. Savoir n'est pas une question technique isolée, mais une manifestation de l'excellence humaine. Les vertus intellectuelles sont des formes d'excellence du caractère, analogues à la bravoure ou à la générosité. Cette continuité entre l'éthique et l'épistémologie reflète une vision aristotélicienne selon laquelle la vérité, comme le bien, n'est pas simplement un objet à acquérir, mais le fruit d'une excellence qu'on cultive. Deuxièmement, elle rend compte de l'intuition que la connaissance est ''méritoire'' ou ''creditworthy'' — digne de crédit. Attribuer une connaissance à quelqu'un, c'est reconnaître en lui une forme d'excellence, un accomplissement personnel. C'est très différent du fait d'une simple coïncidence heureuse. Cette approche capture le caractère ''personnel'' ou ''agentif'' de la connaissance : on connaît comme sujet responsable, en exerçant ses excellences cognitives. Troisièmement, elle élargit le champ de l'analyse épistémologique. Au lieu de se restreindre à des questions de conditions formelles, l'épistémologie des vertus ouvre la réflexion vers des questions de développement moral et cognitif : comment cultive-t-on les vertus intellectuelles ? Quels rôles jouent l'éducation, l'expérience, la pratique ? Comment les défauts de caractère — l'arrogance, la paresse intellectuelle, le dogmatisme — entravent-ils l'accès à la connaissance ? '''Difficultés et réserves critiques''' Néanmoins, l'approche vertueuse rencontre des objections sérieuses. La première concerne la ''clarté conceptuelle'' de la notion de ''vertu intellectuelle''. Quels critères permettent d'identifier une vertu intellectuelle ? La liste proposée par Zagzebski (humilité, courage, persévérance, etc.) est-elle exhaustive ou simplement exemplaire ? Comment distinguer une vertu véritable d'une ''apparence de vertu'' ? Une personne peut sembler exhiber l'humilité tout en étant simplement apathique ou indifférente à la vérité. La deuxième objection porte sur le ''caractère circulaire'' de la définition. Pour savoir si une croyance procède d'une vertu intellectuelle, faut-il d'abord savoir ce qu'est une vertu intellectuelle ? Et pour savoir cela, faut-il d'abord avoir une théorie de la connaissance ? Cette circularité, si elle est véritable, menacerait la prétention de l'épistémologie des vertus à offrir une analyse éclairante de la connaissance. La troisième objection concerne la ''question du relativisme évaluatif''. Si la connaissance repose sur l'exercice de vertus intellectuelles, et si les vertus intellectuelles sont en partie culturellement déterminées (c'est-à-dire si différentes cultures valorisent différentes excellences cognitives), ne risque-t-on pas de sombrer dans un relativisme qui nierait l'universalité des critères épistémiques ?<ref>Jason Baehr, ''The Inquiring Mind: On Intellectual Virtues and Virtue Epistemology'', Oxford University Press, 2011, p. 156-185.</ref> La quatrième objection soulève le problème de la ''justification du lien entre vertu et connaissance''. Pourquoi suppose-t-on que l'exercice d'une vertu intellectuelle garantit ou favorise l'accès à la vérité ? Une personne peut être courageux intellectuellement et néanmoins fortement errer. L'exercice d'une vertu ne semble pas logiquement implique l'atteinte de la vérité. Quel est donc le lien substantiel entre la vertu et la connaissance ? ====== Réception et développements ultérieurs ====== Malgré ces difficultés, l'épistémologie des vertus a exercé une influence croissante sur la réflexion épistémologique contemporaine. Elle a inspiré le développement de théories hybrides qui cherchent à intégrer les intuitions de l'approche vertueuse avec d'autres cadres théoriques — notamment l'épistémologie anti-hasard de Duncan Pritchard, qui conçoit la vertu comme une forme d'exclusion du hasard épistémique nuisible. L'approche vertueuse a également stimulé une attention nouvelle aux questions d'épistémologie sociale : si les vertus intellectuelles sont culturellement situées et s'acquièrent par l'éducation et la pratique sociale, comment les structures de domination et les inégalités sociales affectent-elles le développement différencié de ces vertus ? Cette ouverture vers les questions de justice épistémique et d'équité cognitive constitue l'une des contributions majeures de l'épistémologie des vertus au débat actuel. ===== L'épistémologie anti-hasard de Pritchard ===== '''Le hasard épistémique''' Duncan Pritchard a proposé une synthèse que l'on désigne comme une '''épistémologie anti-hasard'''. L'idée directrice est que la connaissance est une croyance vraie formée de telle sorte qu'elle ne soit pas affectée par certaines formes de ''hasard épistémique'' qui ôteraient au sujet un contrôle suffisant sur la vérité de ce qu'il croit. Pritchard distingue notamment : * un ''hasard de résultat'' : la croyance aurait facilement pu être fausse (c'est ce que la condition de sécurité vise à exclure) ; * un ''hasard de formation'' : le processus cognitif effectivement suivi est inadéquat ou fragile ; * un ''hasard environnemental'' : l'environnement est tel que, dans de nombreuses situations voisines, la même méthode conduirait à des croyances fausses (comme dans le cas des fausses granges). Selon cette perspective, les cas de Gettier mettent au jour une forme déterminée de hasard épistémique : la conjonction fortuite de la justification et de la vérité, là où l'on attendrait que la justification conduise à la vérité d'une manière non contingente.<ref>Duncan Pritchard, ''Epistemic Luck'', Oxford University Press, 2005, p. 168-195.</ref> ===== L'approche contextualiste : variation des critères de connaissance ===== Certains épistémologues, en particulier parmi les contextualistes, soutiennent qu'il n'existe pas de réponse uniforme et définitive au problème de Gettier, parce que le prédicat ''savoir'' est ''contextuel''. Ce que l'on admet légitimement comme connaissance varie selon les contextes d'énonciation et les exigences qui y sont tacitement présupposées. Dans des contextes philosophiques exigeants, les critères de connaissance sont très stricts : dans un tel cadre, les cas de Gettier apparaissent comme des exemples clairs de non-connaissance. Dans des contextes ordinaires, où l'on tolère une certaine marge d'erreur possible, on pourrait être enclin à dire que Smith « sait », pour les besoins de la conversation, que la personne qui obtiendra l'emploi a dix pièces dans sa poche. Le contextualisme rend ainsi compte de la variabilité de nos jugements ordinaires sur le savoir. Mais aux yeux de nombreux critiques, il laisse en suspens la question de savoir ce qu'est la connaissance ''indépendamment'' des fluctuations de contexte : il semble déplacer la question plutôt que d'y répondre frontalement.<ref>Keith DeRose, ''The Case for Contextualism: Knowledge, Skepticism, and Context'', Oxford University Press, 2009.</ref> ===== Bilan : la persistance du désaccord ===== Aucune des réponses proposées au problème de Gettier n'a recueilli un accord général. Chacune met en lumière une intuition légitime — le rôle des antiféatisants, l'importance de la fiabilité, la place de la compétence intellectuelle, l'influence de l'environnement, la variation contextuelle des critères — mais chacune se heurte à des objections précises. Après plus de soixante ans de discussions, le désaccord demeure profond. Ce simple constat — la permanence du problème à travers les décennies — suggère que Gettier a mis au jour une difficulté véritable dans notre compréhension de la connaissance. Il se peut que la connaissance ne puisse pas être entièrement ramenée à un ensemble fini de conditions, qu'il s'agisse de trois, de quatre ou de davantage. Il se peut aussi que les intuitions que nous mobilisons devant les cas de type Gettier ne forment pas un ensemble parfaitement cohérent. Quoi qu'il en soit, la complexité conceptuelle révélée par ces cas continue de nourrir la réflexion épistémologique contemporaine.<ref>Ichikawa, Jonathan L. & Steup, Matthias, « The Analysis of Knowledge », ''Stanford Encyclopedia of Philosophy'', 2018.</ref> ==== 1.4 Connaissances non-propositionnelles ==== ===== Au-delà des propositions ===== Tout ce qui précède s'est concentré sur la connaissance ''propositionnelle'' — la connaissance ''que'' quelque chose est le cas. Mais l'analyse standard de la connaissance présuppose une limitation importante : elle traite la connaissance comme une affaire de croyances vraies justifiées portant sur des propositions. Or plusieurs penseurs ont mis en question ce présupposé, en soutenant qu'il existe d'autres formes de connaissance — des connaissances qui ne se laissent pas réduire à des propositions. Ces connaissances ''non-propositionnelles'' n'ont pas reçu autant d'attention philosophique que la connaissance propositionnelle. Pourtant, elles jouent un rôle central dans nos vies cognitives et dans nos activités pratiques quotidiennes. Ignorer ces formes de connaissance reviendrait à appauvrir considérablement notre compréhension de ce que c'est que connaître. ===== Connaître comment : le savoir-faire ===== ====== Gilbert Ryle et la refondation de la théorie de la connaissance ====== La distinction entre knowing that et knowing how, formulée par Gilbert Ryle dans son article de 1945 intitulé Knowing How and Knowing That, constitue un tournant majeur dans l'histoire de l'épistémologie analytique.<ref>Gilbert Ryle, « Knowing How and Knowing That », ''Proceedings of the Aristotelian Society'', vol. 46, 1945, p. 1-16.</ref> Bien que cette distinction ne soit pas entièrement nouvelle — elle possède des antécédents dans la réflexion aristotélicienne, notamment la distinction entre ''sophia'' (sagesse théorique) et ''phronesis'' (sagacité pratique) — Ryle la reformule en termes modernes et l'inscrit au cœur de l'analyse philosophique du langage et de l'esprit. La portée de l'article de Ryle s'étend bien au-delà de la simple catégorisation des formes de connaissance. Il s'agit d'une intervention critique dans la philosophie de l'esprit et du langage qui remet en question un présupposé fondamental de la tradition cartésienne : l'idée que toute compréhension repose ultimement sur des contenus mentaux explicites, des représentations cognitives articulées. '''La connaissance-que : clarification et délimitation''' Ryle désigne par knowing that la connaissance de propositions, c'est-à-dire la capacité à affirmer, à croire ou à reconnaître comme vraie une proposition portant sur l'état du monde. Cette forme de connaissance est caractérisée par sa structure linguistique : elle s'exprime sous la forme « Je sais que P », où P est une proposition dotée d'une valeur de vérité déterminée. La connaissance-que revêt plusieurs caractéristiques saillantes. D'abord, elle est ''propositionnelle'' : elle porte sur des contenus qui peuvent être formulés explicitement en langage et dont on peut évaluer la vérité. Deuxièmement, elle est ''cognitive'' : elle implique une relation mentale à un contenu — une forme de compréhension ou de représentation. Troisièmement, elle est ''évaluable'' selon les critères de vérité et de fausseté : une connaissance-que peut être correcte ou erronée. Les exemples paraissent triviaux : « Je sais que Paris est la capitale de la France », « Je sais que l'eau bout à 100°C au niveau de la mer », « Je sais que Socrate est le maître de Platon ». Mais cette trivialité apparente masque une complexité considérable. Savoir que P requiert non seulement de croire que P, mais également d'être justifié dans cette croyance et que P soit effectivement vrai — c'est l'analyse tripartite classique que nous avons examinée précédemment. '''La connaissance-comment : une catégorie irréductible''' À l'inverse, knowing how désigne une forme de connaissance fondamentalement différente. Elle s'exprime linguistiquement par la structure « Je sais comment faire X » ou « Je sais comment accomplir Y ». Mais cette similitude syntaxique superficielle ne doit pas nous égarer : la structure logique et ontologique de la connaissance-comment est radicalement distincte. Ryle énumère de nombreux exemples de connaissance-comment : savoir comment jouer au tennis, savoir comment cuisiner un repas, savoir comment conduire une voiture, savoir comment danser la valse, savoir comment écrire élégamment, savoir comment convaincre un interlocuteur.<ref>Gilbert Ryle, ''The Concept of Mind'', Hutchinson, 1949, p. 25-61.</ref> Dans chaque cas, la connaissance ne consiste pas en la possession d'une série de propositions — bien qu'elle puisse ''inclure'' une telle possession — mais plutôt en l'exercice d'une compétence, en la manifestation d'une habileté, en la capacité à accomplir intelligemment une action déterminée. ====== La réfutation rylienne de l'intellectualisme ====== '''Formulation et enjeu de la thèse intellectualiste''' Ryle identifie et critique une position qu'il désigne sous le terme d'''intellectualisme'' : la thèse selon laquelle toute forme de connaissance, y compris la connaissance-comment, se réduit ultimement à la connaissance-que. L'intellectualisme repose sur la conviction que la compréhension d'une action, la maîtrise d'une technique ou l'exercice d'une habileté revient fondamentalement à ''connaître une proposition appropriée''. Selon l'intellectualiste, apprendre à jouer au tennis consiste à acquérir la connaissance d'un ensemble de propositions : les règles du jeu, les principes de la biomécanique du service, les stratégies de placement, les techniques de déplacement, etc. Cette accumulation de connaissance propositionnelle constituerait, selon cette conception, ce qui s'appelle le « savoir-faire ». Le joueur expérimenté se distinguerait du novice non par la possession d'une compétence qualitativement différente, mais simplement par la possession d'un ensemble plus vaste, plus raffiné et mieux intégré de propositions vraies et justifiées concernant le jeu. Cette position possède une certaine apparence de plausibilité. Après tout, on peut enseigner le tennis en expliquant les règles, en formant verbalement les stratégies, en décrivant les gestes appropriés. Et inversement, une personne qui ignore les règles du tennis ne pourra pas jouer correctement. Il semble donc qu'il existe une connexion intime entre la connaissance propositionnelle et la compétence pratique. '''L'argument rylien : l'écart irréductible entre théorie et pratique''' Ryle cependant identifie une lacune logique fondamentale dans le raisonnement intellectualiste. Son argument procède par une réductio ad absurdum subtile et pénétrante. Supposons, en effet, que la connaissance-comment se réduise entièrement à la connaissance-que. Cela signifierait que posséder le savoir-faire consiste à posséder une certaine connaissance propositionnelle. Or, connaissance-que implique, selon l'analyse classique, non seulement de croire une proposition, mais aussi d'être justifié dans cette croyance. Le problème surgit immédiatement : ''qu'est-ce qui justifie'' la croyance à propos de la technique du tennis ? Si c'est une autre proposition, alors on entre dans une régression justificative sans fin. Pour savoir comment servir, faut-il connaître une proposition P décrivant la technique du service ? Mais pour connaître P (au sens de la connaissance-que), faut-il connaître une autre proposition Q qui la justifie ? Et ainsi de suite indéfiniment, nous nous enfonçons dans une régression qui paraît vicieuse. Mais il y a plus fondamental encore. Supposons même que nous possédions, de manière miraculeuse, la totalité des propositions pertinentes — l'ensemble complet et exhaustif de toutes les propositions vraies et justifiées concernant le tennis. Cela suffirait-il pour que nous sachions jouer au tennis ? Manifestement non. Une personne peut connaître absolument tout ce qu'il est possible de connaître de manière propositionnelle au sujet du tennis — toutes les règles, tous les principes de biomécanique, toutes les stratégies — sans pour autant être capable de remporter un match de tennis. Elle demeure une novice maladroite. Inversement — et c'est un point qu'un champion professionnel illustre cruellement — une personne peut posséder un savoir-faire remarquable, une compétence extraordinaire au tennis, tout en étant incapable d'articuler sous forme propositionnelle justifiée les raisons précises de ses actions. Le champion peut ne pas savoir ''pourquoi'' il exécute son service de cette manière plutôt que d'une autre ; il sait simplement ''comment'' le faire, et il le fait avec une efficacité stupéfiante. Interrogé sur sa technique, il peut produire des explications laborieuses qui ne captent que partiellement la finesse réelle de sa compétence. Cette asymétrie révèle un fossé logique insurmontable entre connaissance-que et connaissance-comment. Deux propositions en découlent : # On peut posséder une connaissance-que exhaustive sans posséder la connaissance-comment correspondante. # On peut posséder une connaissance-comment remarquable sans posséder la connaissance-que qui l'expliquerait. Donc, la connaissance-comment ne peut pas se réduire à la connaissance-que. C'est une catégorie d'une irréductibilité logique. ====== La théorie rylienne des capacités et des dispositions ====== '''Le rejet du modèle représentationaliste''' Ryle propose une compréhension alternative de la connaissance-comment qui rompt radicalement avec le modèle intellectualiste. Il refuse l'assimilation de la connaissance-comment à une représentation mentale explicite. Selon sa conception, la connaissance-comment n'est pas une forme de ''contenu mental'', mais plutôt une ''capacité'' ou une ''disposition'' à accomplir une certaine action de manière intelligente et efficace. Cette redéfinition s'enracine dans une critique plus large du modèle cartésien de l'esprit. Le dualisme cartésien, en reléguant l'esprit dans le ''théâtre intérieur'' de la conscience, a tendance à réduire toute compréhension véritable à une représentation explicite, articulée et présente à la conscience. Mais Ryle rejette cette conception comme philosophiquement stérile et phénoménologiquement inexacte. '''Les dispositions comme catégories analytiques''' Ryle introduit une distinction cruciale entre les états mentaux explicites (croyances conscientes, pensées actuelles, etc.) et les ''dispositions''. Une disposition est une tendance récurrente, stable et caractérisable du sujet à se comporter d'une certaine manière dans certaines conditions. Quand je dis « le verre est fragile », je ne décris pas un état présent du verre, mais une disposition — la tendance du verre à se briser s'il est soumis à un impact suffisant. De même, la connaissance-comment doit être comprise non comme un état mental présent, mais comme une ''disposition'' du sujet à accomplir intelligemment une certaine classe d'actions. Savoir comment jouer au tennis, c'est disposer d'une tendance stable, développée par la pratique, à frapper la balle de manière appropriée, à se placer correctement, à exécuter les coups avec efficacité, et à adapter sa stratégie aux circonstances changeantes du jeu. Cette disposition n'existe pas comme une entité mentale cachée quelque part dans l'esprit du sujet. Elle n'est pas une représentation immobile et inerte. C'est plutôt une ''capacité actuelle'' — quelque chose qui s'exerce et se manifeste précisément dans l'action. La connaissance-comment est essentiellement ''performative'' : elle s'actualise dans la performance, dans l'exercice compétent de l'action.<ref>Gilbert Ryle, op. cit., p. 32-45.</ref> '''Caractéristiques de la disposition intelligente''' Ryle établit que la connaissance-comment, en tant que disposition, possède des caractéristiques distinctives : 1. ''L'intelligibilité de l'action'' : la disposition se manifeste dans des actions qui ne sont pas simplement ''correctes'' d'une manière mécanique ou accidentelle, mais qui possèdent une forme d'intelligibilité interne. Le joueur de tennis compétent ne frappe pas simplement la balle ; il la frappe de manière appropriée aux circonstances, en ajustant son coup à la position du filet, à la vitesse de l'approche adverse, au type de terrain, etc. Son action est ''sensée''. 2. ''L'absence de nécessité d'instruction propositionnelle'' : contrairement à ce que l'intellectualiste suggère, la manifestation de la disposition-ne requiert pas une consultation consciente d'un ensemble de propositions. Le champion de tennis ne se ''dit'' pas consciemment, avant chaque coup, : « Selon le principe P et dans la circonstance C, je dois faire X ». Il agit directement, pré-réflexivement, avec une fluidité qui serait entravée par la médiation d'une réflexion propositionnelle explicite. 3. ''L'évaluabilité selon les critères de compétence'' : contrairement à la connaissance-que (évaluée pour sa vérité), la connaissance-comment est évaluée selon des critères de ''compétence'' ou d'''efficacité''. Nous ne demandons pas : « Votre savoir-faire est-il vrai ? » — cette question n'a pas de sens. Nous demandons : « Votre savoir-faire est-il efficace ? Vos actions accomplissent-elles le but ? Reflètent-elles une compréhension appropriée de la situation ? » ====== La distinction entre théorie et pratique comme distinction conceptuelle ====== La distinction rylienne entre connaissance-que et connaissance-comment reflète une distinction plus profonde entre ''théorie'' et ''pratique''. Cette distinction n'est pas simplement une différence d'attitude ou de contexte d'application. Elle touche à la structure même des deux formes de compréhension. Un théoricien du ski — quelqu'un qui a étudié exhaustivement tous les principes physiques du ski, la biomécanique, la géométrie du terrain — peut demeurer incapable de skier efficacement. Inversement, un skieur olympique possède une compétence pratique époustouflante bien qu'il soit incapable de formuler ou même de comprendre les théories scientifiques qui sous-tendent son activité. Cette incommensurabilité révèle que la théorie et la pratique ne sont pas simplement des points différents sur un continuum d'une seule forme de connaissance. Ce sont plutôt deux catégories qualitativement distinctes, dotées de leurs propres critères d'évaluation, de leurs propres modes d'acquisition et de leurs propres structurations conceptuelles. ====== Le débat contemporain : la résurgence de l'intellectualisme ====== '''Jason Stanley et la réduction sophistiquée''' Le consensus rylien en faveur de l'irréductibilité de la connaissance-comment a cependant été remis en question de manière sérieuse dans la philosophie analytique contemporaine. Des penseurs comme Jason Stanley et Timothy Williamson ont formulé une défense modifiée et plus sophistiquée de l'intellectualisme.<ref>Jason Stanley & Timothy Williamson, « Knowing How '', ''The Journal of Philosophy'', vol. 98, n° 8, 2001, p. 411-444.</ref> Stanley soutient que Ryle n'a pas tort de refuser une forme naïve d'intellectualisme selon laquelle la connaissance-comment s'identifierait simplement à la connaissance-que. Mais il propose une position plus nuancée : la connaissance-comment ''est'' effectivement une forme de connaissance propositionnelle, mais d'une variété particulière. Selon Stanley, savoir comment faire quelque chose consiste à connaître une proposition de type particulier — une proposition indexée, contextuelle, qui ''guide l'action intelligente'' dans les circonstances pertinentes. Par exemple, savoir comment servir au tennis consisterait à connaître une proposition de la forme : « C'est la manière appropriée pour moi, dans ces circonstances, d'accomplir le service ». Cette proposition n'est pas une simple description théorique abstraite ; c'est une proposition que le sujet connaît de manière existentiellement engagée et pragmatiquement orientée vers l'action. La proposition en question possède plusieurs caractéristiques : 1. Elle est ''de re'' (concernant les choses elles-mêmes) et indexée au contexte du sujet — elle ne porte pas sur une généralité abstraite, mais sur la situation actuelle du sujet. 2. Elle est ''pratiquement efficace'' — elle guide l'action, elle peut être exécutée, elle s'oriente vers un résultat. 3. Elle est ''acquise par la pratique'' — ce n'est pas une proposition qu'on apprend simplement en lisant un livre, mais une proposition qu'on ''réalise'' progressivement par l'expérience répétée. ====== L'objection anti-intellectualiste : Katalin Farkas et la défense rylienne réactualisée ====== Malgré l'élégance formelle de la position de Stanley, de nombreux philosophes contemporains demeurent convaincus par l'argument rylien fondamental. Katalin Farkas, notamment, a fourni une défense rigoureuse de la thèse rylienne selon laquelle il existe une distinction réelle et irréductible entre connaissance-comment et connaissance-que.<ref>Katalin Balog & Katalin Farkas, « Introspection and the Concept of Phenomenal Consciousness '', dans Gendler, Tamar Szab & Hawthorne, John (dir.), ''Perceptual Experience'', Oxford University Press, 2006, p. 285-312.</ref> Farkas relève une ambiguïté décisive dans la proposition de Stanley. Quand Stanley soutient que la connaissance-comment est une forme de connaissance-que, il utilise le terme ''proposition'' dans un sens étendu, largement redéfini. Mais cette extension conceptuelle ne résout pas le problème rylien fondamental : il existe toujours une différence irréductible entre (a) croire une proposition, même une proposition indexée, guidée par le contexte et pratiquement efficace, et (b) disposer de la capacité à accomplir intelligemment l'action en question. Farkas distingue ainsi la ''connaissance propositionnelle de second ordre'' (connaître une proposition ''à propos'' de comment faire quelque chose) de la ''connaissance-comment authentique'' (disposer véritablement du savoir-faire). La première peut exister sans la seconde — je peux connaître une proposition correcte à propos de comment faire un service au tennis sans savoir vraiment comment le faire. Inversement, la seconde peut exister sans la première — un excellent joueur peut ne pas connaître explicitement la proposition qui décrirait sa compétence. Cette distinction correspond, selon Farkas, à une différence dans les ''critères d'évaluation''. La connaissance propositionnelle est évaluée pour sa vérité ; la connaissance-comment est évaluée pour sa ''compétence'', c'est-à-dire sa capacité effective à produire des actions appropriées dans une gamme de circonstances. ====== Implications philosophiques ====== '''Pour l'analyse du langage et de la signification''' Le débat entre intellectualistes et anti-intellectualistes possède des implications qui s'étendent bien au-delà de la théorie de la connaissance. Il porte sur la question de savoir comment le langage se rapporte à l'action et à la pratique. Si Stanley a raison, alors il est concevable que chaque forme de compréhension puisse être capturée linguistiquement, dans une proposition suffisamment contextualisée. Mais si Farkas et Ryle ont raison, alors il existe des dimensions de la compréhension — précisément celles qui se manifestent dans la pratique compétente — qui ne peuvent jamais être intégralement traduites en langage propositionnel. '''Pour l'épistémologie générale''' Ces enjeux remettent en question l'hypothèse de base de l'épistémologie analytique traditionnelle : que toute connaissance peut être analysée en termes de croyance propositionnelle vraie justifiée. Si la connaissance-comment résiste à cette réduction, alors l'épistémologie doit s'étendre au-delà du domaine des croyances propositionnelles pour embrasser d'autres catégories de compréhension et de capacité. '''Pour la philosophie de l'esprit''' Le débat soulève également des questions fondamentales en philosophie de l'esprit. Le modèle intellectualiste suppose qu'en dernier ressort, toute compréhension réside dans un contenu mental représentationnel. Le modèle rylien suggère au contraire que certaines formes de compréhension — celles qui caractérisent la connaissance-comment authentique — sont essentiellement ''non-représentationnelles'', incarnées, engagées dans l'action en cours. ===== Connaissance par ''acquaintance'' ===== '''Russell et la connaissance immédiate''' Bertrand Russell a proposé une autre distinction importante : celle entre ''knowledge by acquaintance'' (connaissance par ''acquaintance'', ou connaissance par familiarité directe) et ''knowledge by description'' (connaissance par description). La connaissance par ''acquaintance'' est une connaissance immédiate, directe et non inférentielle d’un objet ou d’un contenu. Quand je dis « Je connais Sam », « Je suis familier avec Paris » ou « Je connais le goût de la tsampa », j’exprime une forme de connaissance par ''acquaintance''. Ce n’est pas d’abord une connaissance ''que'' (elle ne se présente pas essentiellement comme l’affirmation d’une proposition vraie) ; c'est plutôt une familiarité directe avec quelque chose. La connaissance par description, en contraste, est une connaissance ''que'' — la connaissance propositionnelle ordinaire, comme lorsque je dis : « Je sais que Paris est la capitale de la France ». Elle est indirecte, inférentielle, et elle dépend d’une description qui identifie l’objet. '''Caractéristiques de la connaissance par ''acquaintance''''' Russell soutient que la connaissance par ''acquaintance'' possède des traits distinctifs : * Elle est ''directe'' : elle ne passe pas par des inférences ou des représentations conceptuelles médiatrices. Je ne conclus pas, à partir d'autres croyances, que je suis en ''acquaintance'' avec Paris ; j’en ai directement conscience. * Elle ne se réduit pas à une proposition vraie : elle ne consiste pas simplement à croire une proposition au sujet de l’objet. Être en ''acquaintance'' avec quelqu’un ne se réduit pas à croire quelque chose à son propos. * Elle est ''fondationnelle'' : selon Russell, toute notre connaissance propositionnelle repose ultimement sur notre ''acquaintance'' avec des objets et des contenus élémentaires. Les propositions que nous pouvons comprendre doivent être composées, en dernière analyse, de termes simples avec lesquels nous sommes directement en rapport d''acquaintance''. '''Débats contemporains''' La conception russellienne de l''acquaintance'' soulève des questions délicates. Comment distinguer exactement l''acquaintance'' de la simple conscience sensorielle ? Peut-on réellement avoir une relation directe et non médiatisée à un objet, ou bien notre conscience passe-t-elle toujours par des représentations mentales interposées ? Certains philosophes contemporains ont contesté l'idée que l''acquaintance'' soit véritablement ''non-propositionnelle''. Ils soutiennent qu'être en ''acquaintance'' avec quelqu'un implique nécessairement certaines croyances propositionnelles minimales — par exemple, au moins la croyance que cette personne existe. D'autres maintiennent qu'il existe une forme de connaissance par ''acquaintance'' logiquement indépendante de toute connaissance propositionnelle explicite. ===== Autres formes de connaissances non-propositionnelles ===== '''Connaissance par contact perceptuel''' Au-delà du savoir-faire et de l''acquaintance'', il existe d'autres formes de connaissance qui semblent résister à l’analyse purement propositionnelle. C’est le cas, par exemple, de la connaissance immédiate de certaines données sensorielles : ce que c’est que voir la couleur rouge, goûter le chocolat, entendre une mélodie précise. Ces états qualitatifs — ce que les philosophes appellent les ''qualia'' — semblent constituer une forme de connaissance difficile, voire impossible, à traduire intégralement en propositions. Si vous me demandez « Qu’est-ce que c’est que de voir la couleur rouge ? », je peux vous donner une description propositionnelle (« c’est une lumière d’une certaine longueur d’onde »), mais cela ne capture pas l’essence de votre expérience immédiate. Il y a dans cette connaissance quelque chose d’irréductiblement vécu. '''Connaissance pratique réfléchie''' Farkas propose également de distinguer certaines formes de connaissance-comment qu’elle qualifie de connaissance ''pratique réfléchie'' : une habileté à accomplir une action, développée et affinée par une réflexion consciente sur la pratique. Ce type de connaissance n’est ni purement propositionnel (il requiert une capacité d’action réelle) ni purement dispositionnel (il implique une dimension de réflexion et d’engagement cognitif). ===== Implications épistémologiques ===== La reconnaissance de formes non-propositionnelles de connaissance a plusieurs implications importantes pour l’épistémologie contemporaine. '''D’abord, elle élargit considérablement le champ de l’épistémologie.''' L’épistémologie ne se réduit pas à l’étude de la manière dont nous acquérons des croyances vraies justifiées au sujet du monde. Elle doit aussi s’intéresser à la manière dont nous acquérons des habiletés, dont nous développons une familiarité avec des lieux et des personnes, dont nous explorons et comprenons notre expérience qualitative. '''Ensuite, cela remet en question l’idée que la vérité soit toujours le bien épistémique ultime.''' La connaissance-comment n’est pas évaluée pour sa vérité ; elle l’est pour sa capacité à nous permettre d’agir efficacement et intelligemment. L''acquaintance'' n’est pas avant tout une question de croyance vraie, mais un rapport direct, familier, souvent non conceptuel, aux choses. '''Enfin, cela suggère que nous ne pouvons pas analyser toutes les formes de connaissance selon le même modèle.''' Les trois conditions de vérité, de croyance et de justification peuvent être pertinentes pour la connaissance propositionnelle, mais elles ne s’appliquent pas de la même manière — ou pas du tout — aux autres formes de connaissance. Par exemple, il n’y a pas de « croyance vraie justifiée » à propos de la manière de faire un geste technique réussi : il y a une habileté, éventuellement réfléchie, qui s’exerce correctement. ===== Conclusion : l’hétérogénéité de la connaissance ===== La philosophie classique de la connaissance a souvent présumé que la connaissance est un phénomène unifié — qu’on pourrait en donner une analyse unique et définitive qui capture l’essence de tous les cas de connaissance. Mais la reconnaissance de formes non-propositionnelles de connaissance suggère une conclusion différente : la connaissance est ''hétérogène''. Nous connaissons de multiples manières. Nous connaissons ''que'' certaines propositions sont vraies. Nous connaissons ''comment'' accomplir certaines actions. Nous connaissons les personnes et les lieux par ''acquaintance''. Nous connaissons ce que c’est que faire l’expérience de telle ou telle qualité sensible. Chacune de ces formes de connaissance mérite une attention philosophique sérieuse, et chacune peut exiger une analyse légèrement différente. Cette pluralité de formes de connaissance rend l’épistémologie à la fois plus complexe et plus riche. Elle nous oblige à réfléchir plus attentivement à ce que nous faisons quand nous affirmons savoir quelque chose. Et elle nous rappelle que la connaissance n’est pas seulement une affaire intellectuelle et théorique, mais aussi une affaire pratique, expérientielle et interpersonnelle. === Chapitre 2 : Les théories de la vérité === ==== 2.1 La théorie de la correspondance ==== ===== Introduction : la théorie la plus intuitive ===== Parmi les théories de la vérité, la théorie de la correspondance est sans doute l'une des plus anciennes et, à première vue, l'une des plus intuitives. Elle affirme une idée simple : '''une proposition est vraie si et seulement si elle correspond à la réalité'''. Si je dis « La neige est blanche », cette affirmation est vraie si, en effet, la neige est blanche dans le monde. Si je dis « Paris est la capitale de la Belgique », cette affirmation est fausse parce qu'elle ne correspond pas à la réalité : Paris est la capitale de la France, non de la Belgique. Cette conception s'accorde avec notre intuition ordinaire de ce qu'est une vérité. Pour savoir si une affirmation est vraie, nous cherchons habituellement à vérifier si elle correspond aux faits. La théorie semble donc saisir quelque chose d'important sur la nature de la vérité. Cependant, comme nous allons le voir, la théorie de la correspondance soulève des questions philosophiques profondes et complexes. Comment explique-t-on précisément ce rapport entre une proposition et la réalité ? Qu'est-ce exactement qu'une ''proposition'' ? Qu'est-ce qu'un ''fait'' ? Qu'entend-on par une ''réalité'' indépendante ? Comment savons-nous que nos croyances correspondent effectivement au monde ? Ces questions occupent les épistémologues et les métaphysiciens depuis plus d'un siècle. ===== Les origines : d'Aristote à la métaphysique classique ===== '''Aristote et la formule classique''' L'idée que la vérité consiste en une correspondance remonte à Aristote. Dans sa ''Métaphysique'', il énonce : « Dire que ce qui est n'est pas, ou que ce qui n'est pas est, c'est faux ; dire que ce qui est est, et que ce qui n'est pas n'est pas, c'est vrai. » Cette formule établit l'intuition fondamentale de la théorie de la correspondance : la vérité est l'accord entre ce qu'on dit et la réalité. Si la réalité est d'une certaine manière, alors dire que c'est ainsi constitue une vérité ; si la réalité est autrement, alors le dire serait faux. Toutefois, Aristote lui-même ne développe pas une théorie systématique et détaillée de la vérité. Son énoncé demeure plutôt une observation métaphysique générale. Ce n'est que beaucoup plus tard que les philosophes modernes entreprennent de construire une véritable théorie épistémologique de la correspondance. ===== La version moderne : Russell et Moore ===== '''Bertrand Russell et le fait''' Au début du XX{{e}} siècle, Bertrand Russell et George Edward Moore élaborent une version plus sophistiquée de la théorie de la correspondance. Russell formule clairement le noyau de la théorie : dire qu'une croyance est vraie, c'est dire qu'il existe dans l'univers un fait auquel elle correspond ; dire qu'elle est fausse, c'est dire qu'il n'existe dans l'univers aucun fait auquel elle correspond. Russell insiste sur l'importance décisive de l'existence du ''fait''. Pour qu'une croyance soit vraie, il faut qu'existe dans la réalité quelque chose — un fait — qui la rend vraie. La vérité ne dépend pas uniquement de notre manière de penser ; elle dépend d'une réalité objective, extérieure et indépendante de nos croyances. '''Moore et les états de choses''' George Edward Moore, de manière analogue, défend l'idée d'une correspondance entre la croyance et la réalité. Il soutient que les croyances vraies correspondent à des états de choses (''states of affairs'') qui existent effectivement dans l'univers, tandis que les croyances fausses prétendent correspondre à des états de choses qui, eux, n'existent pas. La contribution importante de Russell et Moore consiste à rendre explicite le besoin de préciser ce que signifie exactement cette ''correspondance''. Ils reconnaissent qu'on ne peut pas se contenter d'affirmer qu'une proposition ''correspond'' à un fait ; il faut expliquer en quoi consiste ce rapport de correspondance. ===== Les trois composantes de la théorie ===== '''1. Les porteurs de vérité (''truth-bearers'')''' La première question qu'une théorie de la correspondance doit affronter est la suivante : quelles sont les entités qui peuvent être vraies ou fausses ? S'agit-il : * des ''phrases'' ou ''énoncés'' (les formulations linguistiques concrètes) ? * des ''propositions'' (les significations ou contenus abstraits des phrases) ? * des ''croyances'' (les états mentaux des sujets) ? Russell et Moore font, selon les périodes de leur pensée, des choix différents. Russell privilégie d'abord les ''propositions'' comme porteurs fondamentaux de vérité et de fausseté, avant de réviser sa position. Moore, pour sa part, insiste sur l'importance des propositions, considérées comme des entités abstraites, indépendantes de nos pensées. La plupart des théoriciens contemporains de la correspondance considèrent que les ''propositions'' sont les porteurs primaires de vérité. Une proposition est alors le contenu signifié par une phrase, indépendamment de la langue utilisée pour l'exprimer. '''2. Les entités de la réalité (''truth-makers'')''' La deuxième question est : à quoi les propositions doivent-elles correspondre ? À des ''faits'' ? À des ''états de choses'' ? À des combinaisons d'''objets et de propriétés'' ? Russell et Moore parlent de ''faits''. Un fait, selon eux, est une entité complexe qui fait partie de la structure du monde. Par exemple, le fait que la neige est blanche est une entité qui existe dans le monde et qui rend vraie la proposition « La neige est blanche ». Mais la notion de ''fait'' s'avère problématique. Existe-t-il des faits négatifs (le fait que X n'existe pas) ? Existe-t-il des faits disjonctifs correspondant à des propositions disjonctives (comme « Il pleut ou il neige ») ? Si oui, le nombre de faits qui existent paraît étrange et démesurément proliférant. Sinon, comment une théorie de la correspondance peut-elle rendre compte de la vérité des propositions négatives et disjonctives ? Pour tenir compte de ces difficultés, certains auteurs parlent plutôt de ''vérifacteurs de vérité'' (''truth-makers'') : des entités ou situations réelles, de types éventuellement variés, qui suffisent à rendre vraies certaines propositions. '''3. La relation de correspondance''' La troisième question est la plus délicate : qu'est-ce que cette ''correspondance'' elle-même ? Comment exactement une proposition ''correspond-elle'' à un fait ou à un vérifacteur de vérité ? Deux grandes approches se sont dégagées. '''L'approche structurale''' Selon l'approche structurale, une proposition et un fait correspondent si leurs structures sont isomorphes : si leurs constituants sont agencés de la même manière. Par exemple, la proposition « Socrate est sage » possède la structure [sujet = Socrate, prédicat = sage]. Si le fait correspondant possède également cette structure interne, alors il y a correspondance entre la proposition et le fait. '''L'approche non structurale''' Selon l'approche non structurale, la correspondance n'est pas une relation d'isomorphie détaillée, mais une corrélation plus simple : le fait qu'une proposition soit vraie consiste simplement en l'existence d'un vérifacteur qui la rend vraie, sans qu'il soit nécessaire de postuler une correspondance structurale fine entre ses constituants et ceux du fait. ===== Les défis majeurs de la théorie ===== '''Le problème des vérités complexes''' Considérons la proposition « Soit il pleut, soit il neige ». Existe-t-il un ''fait disjonctif'' — un état de choses consistant en une disjonction — dans la réalité ? L'idée paraît étrange. Ou prenons la proposition « Il n'est pas vrai que la Lune est faite de fromage ». Faut-il supposer un ''fait négatif'' pour rendre cette proposition vraie ? La théorie semble exiger une ontologie baroque, chargée de faits négatifs, disjonctifs, conditionnels, etc., pour rendre compte de toutes les vérités. '''Le problème épistémologique''' Comment savons-nous qu'une proposition correspond réellement à un fait ? L'objection classique est que nous ne pouvons jamais ''sortir de notre esprit'' pour vérifier directement si nos croyances correspondent au monde. Nous sommes enfermés dans notre perspective subjective et nous n'accédons au monde qu'au travers de nos perceptions et de nos pensées. Si la vérité consiste en la correspondance entre croyance et réalité, mais que cette correspondance est en elle-même inobservable, comment pouvons-nous jamais ''savoir'' que nos croyances sont vraies ? Ce problème ouvre la voie au scepticisme : si la correspondance est la norme de la vérité, mais que nous ne pouvons jamais vérifier cette correspondance de façon indépendante, notre prétention à la connaissance semble constamment menacée. '''L'objection kantienne''' Immanuel Kant objecte que nous ne pouvons jamais accéder aux ''choses en soi'' (noumènes) indépendamment de nos catégories conceptuelles. Nous connaissons seulement les choses telles qu'elles nous apparaissent (phénomènes), c'est-à-dire telles qu'elles sont déjà structurées par nos formes de sensibilité et nos catégories de l'entendement. Dès lors, la théorie de la correspondance devient problématique : à quoi exactement nos propositions correspondent-elles ? Correspondent-elles à la réalité telle qu'elle nous apparaît ? Dans ce cas, la ''correspondance'' ne serait pas une relation à une réalité indépendante, mais à une réalité déjà filtrée par notre appareillage conceptuel. Correspondent-elles à la réalité telle qu'elle est en elle-même, indépendamment de toute expérience ? Mais, dans ce cas, comment pourrions-nous jamais connaître ou vérifier une telle correspondance, puisque le noumène nous est par principe inaccessible ? ===== Tentatives contemporaines de reconstruction ===== '''Wittgenstein et la théorie figurative''' Ludwig Wittgenstein, dans le ''Tractatus Logico-Philosophicus'' (1921), propose une version raffinée de la correspondance appelée ''théorie figurative'' (''picture theory''). Selon Wittgenstein, une proposition fonctionne comme une ''image'' d'une réalité possible. Une proposition est vraie si l'état de choses possible qu'elle représente est effectivement un état de choses actuel dans le monde. L'intuition de Wittgenstein met en valeur l'idée suivante : une proposition ''figure'' une situation, un peu comme un dessin figure un objet. Les éléments de la proposition correspondent aux éléments de la réalité, et leur agencement correspond à l'agencement des choses dans le monde. Cependant, Wittgenstein lui-même reconnaîtra plus tard que cette théorie figurative est insuffisante, en particulier pour rendre compte des propositions logiques complexes ou des énoncés portant sur des objets abstraits. Dans les ''Investigations philosophiques'', il s'éloigne largement de la théorie de la correspondance pour adopter une conception plus pragmatique du sens (la ''théorie de l'usage'' du langage), centrée sur les jeux de langage et les pratiques d'usage plutôt que sur l'image du monde. '''Les théories contemporaines du ''truthmaking''''' Certains philosophes contemporains, comme David Armstrong, tentent de reconstruire le projet de la correspondance sous la forme d'une ''théorie du ''truthmaking'''' (ou des ''vérifacteurs de vérité''). Ils soutiennent que toutes les vérités sont ultimement rendues vraies par des entités objectives dans le monde. Cette approche reconnaît les difficultés traditionnelles, tout en essayant de les reformuler. Selon ces théoriciens, nous n'avons pas besoin de ''faits'' au sens lourd de Russell. Il suffit de dire qu'il existe ''quelque chose'' dans le monde (une situation, un état de choses, une configuration d'objets et de propriétés) qui rend une proposition vraie. Ce ''vérifacteur'' détermine comment le monde doit être pour que la proposition soit vraie. On peut également mentionner la ''conception sémantique de la vérité'' proposée par Alfred Tarski. Pour un langage formalisé, Tarski estime qu'une théorie de la vérité est adéquate si elle permet de démontrer, pour chaque phrase « p » du langage-objet, un schéma de la forme : ''« p » est vraie si et seulement si p'' (par exemple : ''« La neige est blanche » est vraie si et seulement si la neige est blanche''). Cette approche, souvent interprétée comme une version formelle de la théorie de la correspondance, vise à relier de façon rigoureuse les expressions du langage à ce qui doit être le cas dans le monde pour qu'elles soient vraies. ===== Avantages et limites de la théorie ===== '''Avantages''' La théorie de la correspondance s'accorde remarquablement bien avec notre intuition ordinaire selon laquelle dire la vérité revient à ''dire les choses comme elles sont''. Elle exprime de manière simple l'idée que la vérité ne dépend pas de ce que nous voulons ou ressentons, mais de la manière dont est effectivement le monde. Elle met également l'accent sur le caractère objectif de la vérité : la valeur de vérité d'une proposition dépend d'une réalité extérieure à nos croyances. Que nous le voulions ou non, si « Le chat est sur le tapis » cesse d'être vrai lorsque le chat s'éloigne du tapis, c'est parce qu'un changement réel dans le monde modifie la valeur de vérité de notre énoncé. Enfin, la théorie de la correspondance fournit une base naturelle au réalisme sémantique : le sens des propositions peut être compris à partir de ce qui les rendrait vraies. Comprendre une proposition, c'est savoir dans quelles conditions du monde elle serait vraie ou fausse. '''Limites''' La notion de ''correspondance'' elle-même demeure obscure. Dire qu'une proposition ''correspond'' à un fait ne suffit pas : il faut expliquer en quoi consiste cette correspondance, et c'est précisément ce qui se révèle difficile à formuler sans recourir à des métaphores (image, miroir, reflet, etc.). La théorie semble en outre impliquer une ontologie lourde et peu intuitive : pour chaque proposition vraie, faudrait-il postuler un ''fait'' correspondant, y compris pour les vérités négatives, disjonctives ou hautement générales ? On risque alors de multiplier les entités métaphysiques de manière peu parcimonieuse. Le problème épistémologique demeure lui aussi préoccupant : si la vérité consiste en la correspondance entre nos croyances et le monde, mais que cette relation de correspondance ne peut jamais être directement observée, comment pouvons-nous justifier notre prétention à connaître ? La théorie paraît ici vulnérable aux arguments sceptiques. Enfin, l'objection kantienne fait planer un doute plus profond : si toute notre expérience du monde est déjà structurée par nos formes de sensibilité et nos catégories conceptuelles, est-il encore cohérent de parler de ''correspondance'' avec une réalité totalement indépendante de ces formes ? La théorie de la correspondance doit alors soit renoncer à une partie de ses prétentions réalistes fortes, soit accepter une forme de modestie quant à ce que nous pouvons réellement connaître de la réalité ''en soi''. ===== Conclusion : une théorie persistante ===== Malgré ses difficultés manifestes, la théorie de la correspondance demeure l'une des théories de la vérité les plus influentes et les plus vigoureusement défendues. Cela tient en partie à son accord avec notre compréhension ordinaire de la vérité, et en partie au fait que les théories concurrentes (théorie de la cohérence, pragmatisme, approches déflationnistes) rencontrent leurs propres problèmes sérieux. La théorie de la correspondance n'est plus aujourd'hui celle d'Aristote, ni même celle de Russell et de Moore. Elle s'est transformée, raffinée, technicisée. Mais la même intuition centrale continue de la porter : il existe quelque chose dans le monde qui rend nos propositions vraies ou fausses. Ce noyau dur de l'idée de correspondance résiste étonnamment bien à la critique, même après des décennies de débats intenses, et continue de structurer une grande partie de la réflexion contemporaine sur la vérité. ==== 2.2 La théorie de la cohérence ==== ===== Introduction : une alternative à la correspondance ===== Si la théorie de la correspondance affirme que la vérité consiste dans l'accord entre propositions et réalité, la théorie de la cohérence propose une conception d'une autre nature : '''une proposition est vraie si et seulement si elle s'inscrit de manière cohérente dans un système plus large de propositions'''. Au lieu de chercher un ''lien'' mystérieux entre proposition et monde extérieur, la théorie de la cohérence se tourne vers l'intérieur : vers les relations entre les croyances et les propositions elles-mêmes. Cette théorie s'inscrit dans une tradition philosophique ancienne, notamment celle de l'idéalisme britannique des XIX{{e}} et XX{{e}} siècles, et elle a été considérablement développée et sophistiquée par des épistémologues contemporains comme Laurence BonJour et Keith Lehrer. ===== Les origines idéalistes ===== '''L'idéalisme de Bradley et Blanshard''' La théorie de la cohérence émerge historiquement de la philosophie idéaliste. Francis Herbert Bradley, grand philosophe idéaliste britannique du XIX{{e}} siècle, soutient que la réalité ultime consiste en un tout intégré et cohérent : l'Absolu. Rien de particulier ou d'isolé n'est vraiment vrai en soi ; seule la totalité complète et parfaitement cohérente possède la plénitude de la vérité. Brand Blanshard reprend ultérieurement ce projet et formule un argument clé. Si la vérité consiste en une correspondance à des ''faits'' objectifs, comment saurions-nous qu'une proposition correspond réellement aux faits ? Nous ne pouvons jamais ''sortir'' de notre système de croyances pour vérifier directement la correspondance. Nous demeurons toujours à l'intérieur de nos pensées. La seule mesure de la vérité qui nous soit véritablement accessible paraît donc être la cohérence interne du système de croyances. ===== La structure de la théorie ===== '''Le concept central de cohérence''' La théorie de la cohérence soutient que la vérité consiste dans la cohérence mutuelle des propositions au sein d'un système intégré. Mais qu'entend-on exactement par ''cohérence'' ? La question est plus complexe qu'il n'y paraît. '''Cohérence et consistance''' Certains pensent que la cohérence se réduit à la consistance logique ou à l'absence de contradiction. Mais cela ne suffit pas. Un ensemble de propositions pourrait être logiquement consistant sans présenter de véritable ''cohérence''. Par exemple, une collection de propositions totalement indépendantes les unes des autres pourrait être consistante, tout en manquant totalement d'unité ou d'intégration. '''Cohérence et soutien mutuel''' Une conception plus riche, inspirée notamment par Bradley, voit la cohérence dans le soutien mutuel et l'intégration systématique des propositions. Les propositions cohèrent lorsqu'elles s'expliquent et se soutiennent mutuellement, formant un ensemble organique où chaque partie s'imbrique avec les autres de manière significative. '''Cohérence et implications logiques''' Une autre approche met l'accent sur les implications logiques. Une proposition cohère véritablement avec un système lorsqu'elle est impliquée par d'autres propositions du système, ou lorsqu'elle les implique à son tour, d'une manière qui renforce l'unité et la capacité explicative de l'ensemble. ===== Les théoriciens majeurs ===== '''Laurence BonJour et la structure systématique''' Laurence BonJour a développé une théorie sophistiquée de la cohérence pour la justification épistémique. Selon lui, une croyance est justifiée si elle cohère adéquatement avec le reste du système de croyances d'une personne. BonJour insiste sur un point crucial : il ne s'agit pas seulement de consistance logique. La véritable cohérence comporte plusieurs dimensions articulées : 1. Une '''consistance interne''' : absence de contradiction logique manifeste au sein du système de croyances.<br> 2. Un '''soutien mutuel''' : les croyances se renforcent et s'expliquent réciproquement.<br> 3. Une certaine '''complétude''' : le système couvre et explique aussi largement que possible les domaines de l'expérience concernés.<br> 4. Une '''simplicité''' relative : le système s'organise de manière économique et évite les complications inutiles. BonJour introduit également la notion de ''système cognitif évalué'', pour souligner que les croyances ne fonctionnent jamais isolément, mais toujours comme des éléments d'un réseau systématique complexe et interconnecté. '''Keith Lehrer et le système d'évaluation''' Keith Lehrer propose une conception apparentée mais distincte, où la cohérence dépend précisément de la manière dont une croyance s'insère dans le système plus large des croyances d'une personne. Pour Lehrer, une croyance est justifiée si elle s'intègre mieux que ses rivales dans ce qu'il appelle le ''système d'évaluation''. Ce système comprend non seulement les croyances de premier niveau, mais aussi des croyances de niveau supérieur, c'est-à-dire des croyances que le sujet possède ''au sujet de ses croyances'' (par exemple : « mes perceptions ordinaires sont généralement fiables »). ===== Avantages de la théorie de la cohérence ===== '''Éviter le problème épistémologique central''' Le grand avantage de la théorie de la cohérence, par rapport à la correspondance, est qu'elle semble éviter le problème épistémologique central : comment vérifier la correspondance à une réalité indépendante et, en un sens, inaccessible ? Dans le cadre cohérentiste, nous n'avons besoin que de comparer les propositions entre elles, ce qui paraît épistémiquement accessible et dépourvu de mystère métaphysique. '''Intégration systématique des croyances''' La théorie met en valeur une intuition importante : nos croyances forment un système intégré et interdépendant, plutôt qu'une collection chaotique de propositions isolées. Les croyances se soutiennent mutuellement et s'organisent en un réseau où chacune influe sur les autres. La cohérence devient ainsi un idéal rationnel pour nos systèmes de croyances. '''Rôle dans la pratique scientifique''' Dans la pratique réelle de la science, la cohérence joue un rôle central. Les théories scientifiques ne sont jamais testées isolément contre des ''faits bruts'' ; elles sont toujours confrontées à l'expérience comme des systèmes entiers. On ajuste les hypothèses aux marges, on revoit des postulats auxiliaires, on réorganise parfois toute une théorie pour préserver au mieux la cohérence globale. La théorie de la cohérence semble donc bien refléter cette dimension systématique et structurelle de la méthode scientifique. ===== Les défis majeurs de la théorie ===== '''Le problème de l'isolation (''isolation objection'')''' L'objection la plus célèbre vient de Bertrand Russell. Le simple fait qu'un système de croyances soit cohérent ne garantit nullement qu'il soit vrai. Un système entier pourrait être parfaitement cohérent, logiquement impeccable, et pourtant complètement faux, s'il n'entretient aucun rapport avec la réalité objective. Russell oppose ainsi à Blanshard l'idée qu'un système de croyances pourrait être intérieurement très harmonieux et cependant totalement déconnecté du monde réel. La cohérence interne ne semble donc jamais, à elle seule, une garantie de vérité. Ce qui importe, objectent les critiques, c'est le rapport à la réalité, non seulement l'harmonie interne. '''Le problème des systèmes rivaux incompatibles''' On peut aussi imaginer deux cosmologies entièrement différentes : l'une dans laquelle la Lune existe, l'autre où elle n'existe pas. Chacune pourrait, en principe, former un système de croyances entièrement cohérent, pourvu que l'on ajuste en conséquence tous les énoncés astronomiques et géophysiques. Pourtant, logiquement, elles ne peuvent pas être toutes deux vraies. Si la cohérence était le seul critère de la vérité, il serait difficile d'expliquer comment trancher entre deux systèmes rivaux également cohérents. '''Le problème des degrés de vérité''' La théorie de la cohérence semble impliquer que la vérité serait une affaire de degrés. Un système plus cohérent qu'un autre serait, en un certain sens, ''plus vrai'' que lui. Mais cela paraît contre-intuitif. Nous avons tendance à penser que les propositions vraies sont tout simplement vraies, non pas seulement ''plus vraies'' ou ''moins vraies'' que d'autres, même si, bien sûr, elles peuvent être plus ou moins bien justifiées. '''Le risque de déconnexion avec l'expérience''' Enfin, on peut objecter qu'un système théorique parfaitement cohérent pourrait, en principe, ignorer ou contredire systématiquement l'expérience perceptuelle. Si la cohérence est le critère ultime, un système hautement harmonieux pourrait justifier des croyances qui s'opposent frontalement à ce que nos sens nous donnent à voir. Comment, dans ce cas, la théorie pourrait-elle préserver le rôle intuitivement central de l'expérience dans la formation et la révision de nos croyances ? ===== Réponses des théoriciens de la cohérence ===== '''Distinguer cohérence et simple consistance''' Les défenseurs contemporains de la théorie de la cohérence répondent d'abord que leurs adversaires confondent souvent ''cohérence'' et ''consistance logique''. La cohérence véritable, insistent-ils, comprend un rapport structuré à l'expérience. BonJour, par exemple, soutient que les croyances perceptuelles élémentaires jouent un rôle particulier dans le système : elles ne sont pas infaillibles, mais elles occupent une place singulière dans l'économie globale de la justification. '''La cohérence n'est pas purement interne''' Plusieurs auteurs refusent aussi l'idée que la cohérence soit une affaire purement interne aux croyances. Nicholas Rescher, par exemple, soutient qu'une croyance n'est vraie ou justifiée que si elle cohère avec l'ensemble des ''candidats à la vérité'' : les propositions qui ont une légitime prétention à être vraies, y compris celles qui sont directement fondées sur l'expérience sensorielle. L'expérience n'est donc pas exclue, mais intégrée à l'intérieur même du système cohérentiste. '''L'hypothèse du système optimal''' Pour répondre au problème des systèmes rivaux, certains théoriciens avancent l'idée d'un ''système optimal''. Ce qui compte, en dernière analyse, serait la cohérence avec le système de croyances qui maximiserait à la fois l'unité, la complétude, la simplicité et l'adéquation à l'expérience. En principe, un seul système pourrait atteindre ce degré optimal de cohérence globale, ce qui permettrait de surmonter le risque d'indétermination entre systèmes concurrents. ===== Les variantes contemporaines : au-delà de la cohérence pure ===== '''La cohérence explicative''' Paul Thagard et d'autres ont développé des approches de ''cohérence explicative'', selon lesquelles deux croyances cohèrent véritablement si elles s'expliquent mutuellement de manière satisfaisante, y compris sur le plan causal. Ce n'est pas seulement la consistance logique ou le soutien mutuel qui compte, mais la capacité explicative globale du réseau de croyances et la manière dont il relie les phénomènes entre eux. '''Le ''foundherentism'' de Susan Haack''' Susan Haack propose un modèle hybride, qu'elle appelle ''foundherentism'', qui emprunte à la fois au fondationnalisme et au cohérentisme. Selon elle, les croyances perceptuelles élémentaires jouent un rôle particulier dans notre système de justification (comme le soutient le fondationnalisme), mais leur propre justification dépend aussi de leur insertion dans le réseau plus large des croyances (comme le souligne le cohérentisme). La justification résulte donc à la fois d'un ''appui'' (foundation) et d'une ''cohésion'' (coherence). '''Réintégration de l'expérience''' Les théoriciens contemporains reconnaissent largement que la cohérence seule ne suffit pas pour rendre compte de la vérité. La cohérence doit s'accompagner d'une bonne ''correspondance'' ou d'un bon ''alignement'' avec l'expérience perceptuelle et les données observables. Cette reconnaissance conduit, en pratique, à des modèles hybrides qui combinent des éléments de correspondance et des exigences de cohérence systématique. ===== Conclusion : la persistance du débat ===== La théorie de la cohérence demeure attrayante pour plusieurs raisons solides. Elle évite certaines des difficultés ontologiques de la théorie de la correspondance (pas besoin de multiplier les ''faits'' problématiques). Elle met en lumière un trait réel de notre vie cognitive : nos croyances forment un système qui doit être organisé et cohérent pour être rationnellement défendable. Cependant, l'objection de l'isolation reste redoutable. La seule cohérence, même enrichie par des liens étroits avec l'expérience, ne semble pas suffire pour saisir ce que nous entendons ordinairement par ''vérité''. Nous conservons une intuition tenace : la vérité concerne avant tout ''la manière dont le monde est réellement'', et pas seulement l'organisation interne de nos croyances. C'est pourquoi beaucoup d'épistémologues contemporains explorent aujourd'hui des voies de synthèse : des conceptions où la vérité implique à la fois la cohérence d'un système de croyances et une certaine forme de contact adéquat avec une réalité objective. Dans cette perspective, la théorie de la cohérence n'est pas purement abandonnée ; elle est réinterprétée comme l'une des composantes nécessaires, mais non suffisantes, d'une compréhension plus complète de la vérité. ==== 2.3 La théorie pragmatiste ==== ===== Introduction : la vérité au service de l'action ===== Si la théorie de la correspondance regarde vers l'extérieur (vers la réalité) et la théorie de la cohérence regarde vers l'intérieur (vers les relations entre croyances), le pragmatisme propose un déplacement plus radical : '''une proposition est vraie si et seulement si elle « fonctionne », c’est-à-dire si, lorsqu’on l’adopte, elle produit les conséquences pratiques attendues et permet d’agir efficacement'''. Plutôt que de demander « correspond-elle au réel ? » ou « cohère-t-elle avec d’autres croyances ? », le pragmatiste demande avant tout : « est-elle utile ? fonctionne-t-elle ? » Le pragmatisme émerge comme un mouvement philosophique spécifiquement américain au tournant du XX{{e}} siècle, avec trois grandes figures : Charles Sanders Peirce, William James et John Dewey. Chacun propose une version légèrement différente du pragmatisme, mais tous partagent l’intuition centrale selon laquelle la vérité est inséparable de l’action pratique et de la résolution des problèmes. ===== Charles Sanders Peirce et la maxime pragmatique ===== '''Le fondateur du pragmatisme''' Charles Sanders Peirce (1839-1914) est généralement considéré comme le fondateur du pragmatisme. Sa contribution majeure réside dans ce qu’il appelle la ''maxime pragmatique'' (''pragmatic maxim''), énoncée pour la première fois en 1878 dans son article ''How to Make Our Ideas Clear'' (« Comment rendre claires nos idées »). Selon Peirce, la maxime pragmatique peut se formuler ainsi : « Considérez quels sont les effets pratiques que nous concevons que l’objet de notre conception possède. Alors, la totalité de notre conception de cet objet réside dans la représentation de ces effets. » Autrement dit, le sens d’un concept réside intégralement dans ses conséquences pratiques concevables. Si deux conceptions n’entraînent aucune différence pratique — c’est-à-dire aucune différence observable dans les conséquences qu’elles impliqueraient — alors elles ne sont, en réalité, qu’une seule et même conception. '''La vérité comme point de convergence de l’enquête''' Pour Peirce, la vérité n’est pas d’abord une propriété statique possédée par une proposition à un moment donné. La vérité est ce vers quoi tendrait ultimement l’enquête scientifique collective après un processus suffisamment prolongé : « La vérité consiste dans la concordance d’une affirmation abstraite avec la limite idéale vers laquelle l’enquête illimitée ferait converger la croyance scientifique. » Peirce introduit ainsi le concept d’''opinion finale'' : la vérité est ce que l’ensemble des enquêteurs accepterait ultimement après un processus d’investigation poussé aussi loin que possible. Il s’agit d’une conception profondément communautaire et dynamique de la vérité : la vérité n’est pas ce qu’un individu isolé croit ici et maintenant, mais ce que la communauté scientifique accepterait à la limite d’une enquête idéale. ===== William James et la pragmatique du « fonctionnement » ===== '''La formule célèbre : « ce qui fonctionne »''' William James (1842-1910) a largement popularisé le pragmatisme et lui a donné une formulation plus accessible. Sa phrase la plus célèbre — et la plus controversée — affirme que le ''vrai'' n’est que « l’expédient dans notre manière de penser », de même que le ''juste'' serait « l’expédient dans notre manière d’agir ». Pour James, la vérité réside dans l’efficacité pratique d’une idée. Une idée vraie est une idée qui ''fonctionne'' : elle nous permet de nous orienter avec succès dans l’expérience, de résoudre des problèmes réels, de simplifier et d’unifier notre vie mentale. James décrit ainsi une idée vraie comme : : « Toute idée avec laquelle nous pouvons entrer utilement en rapport avec notre expérience, qui nous porte avec succès d’une partie de notre expérience à une autre, qui relie les choses de manière satisfaisante, qui fonctionne de façon fiable, simplifie notre tâche, économise notre effort, est vraie dans la mesure où elle fonctionne, vraie ''instrumentalement''. » '''L’utilité comme critère de vérité''' James insiste sur l’idée que la vérité doit être interprétée en termes de conséquences pratiques. La « valeur concrète » d’une croyance vraie est sa capacité à produire une différence tangible et observable dans nos vies. Si croire que X produit exactement les mêmes résultats pratiques que croire que Y, alors il n’existe pas, pour nous, de différence significative de vérité entre X et Y. Cependant, James reconnaît une limite importante : l’utilité immédiate ne suffit pas. Une croyance n’est véritablement utile — et donc digne d’être tenue pour vraie — que si elle continue de fonctionner à long terme, si elle reste en accord, à terme, avec la « résistance » de la réalité. Croire que mon partenaire m’est fidèle alors qu’il ne l’est pas peut sembler utile pendant un temps, mais ce n’est pas une croyance véritablement vraie : tôt ou tard, la confrontation avec les faits réels produira conflit, souffrance et désillusion. ===== John Dewey et l’instrumentalisme épistémologique ===== '''L’extension pragmatiste à la méthode''' John Dewey (1859-1952) étend le pragmatisme bien au-delà d’une simple théorie de la vérité. Il développe ce qu’il appelle l’''instrumentalisme'' : l’idée que nos concepts, nos théories et nos croyances sont des instruments au service de la résolution de problèmes pratiques et de la transformation de notre environnement. Pour Dewey, une croyance est vraie si, lorsqu’on l’emploie effectivement dans l’action, elle produit les conséquences attendues et prédites. La vérité n’est pas une propriété attachée de manière définitive à une phrase abstraite, mais le résultat d’un processus de mise à l’épreuve : celui de la ''vérification'' par l’action. Une proposition n’est pas encore pleinement dite vraie ou fausse tant qu’elle n’a pas été soumise à l’expérience ; c’est le processus de contrôle pratique qui lui confère son statut. Dewey applique cette vision pragmatiste à des domaines très variés — l’éducation, la démocratie, les questions sociales et écologiques — pour montrer que la vérité dépend toujours des contextes pratiques et des problèmes concrets que nous cherchons à résoudre. ===== Les caractéristiques communes du pragmatisme ===== Malgré leurs différences, les trois grands pragmatistes partagent plusieurs traits fondamentaux : * '''La maxime pragmatique''' : le sens et la portée de nos concepts doivent être compris à travers leurs effets pratiques concevables. * '''L’enquête comme processus continu''' : la vérité n’est pas un état figé, mais le résultat d’un processus ininterrompu d’enquête, de mise à l’épreuve et de révision. * '''Le faillibilisme''' : aucune croyance n’est absolument à l’abri de la révision ; toutes nos convictions restent susceptibles d’être corrigées à la lumière de nouvelles expériences. * '''L’importance de la communauté''' : la vérité n’est pas ce que tel individu estime vrai, mais ce vers quoi tendrait, en principe, l’enquête collective d’une communauté de chercheurs. * '''L’orientation pratique de la vérité''' : une vérité doit faire une différence réelle ; elle doit se manifester dans nos pratiques, nos décisions, notre capacité à résoudre des problèmes. ===== Avantages de l’approche pragmatiste ===== '''Éviter l’abstraction métaphysique stérile''' Le pragmatisme offre un antidote puissant à certaines formes d’abstraction métaphysique très détachées de l’expérience. Plutôt que de se demander dans l’absolu si une théorie « correspond parfaitement » à une réalité indépendante, on pose une question plus concrète : ''que permet-elle effectivement de faire ?'' Quelles différences pratiques introduit-elle dans notre manière de vivre, de prévoir, d’agir ? '''Rendre compte de la science réelle''' La théorie pragmatiste éclaire un trait essentiel de la science effective : la recherche progresse en formulant des hypothèses, en en déduisant des conséquences observables, puis en confrontant ces conséquences à l’expérience. La vérité scientifique apparaît intrinsèquement liée à ce qui ''marche'' dans la pratique expérimentale : une théorie est dite vraie tant qu’elle permet des prédictions correctes et une action réussie sur le monde. '''Souplesse contextuelle''' Le pragmatisme autorise une certaine souplesse contextuelle : une même question peut se poser différemment selon les problèmes pratiques en jeu. Des théories différentes peuvent être pertinentes, ou même concurrentes, dans des contextes distincts. Le pragmatisme permet de rendre compte du fait qu’une théorie puisse être plus « vraie pour nous » dans un contexte donné parce qu’elle y fonctionne mieux, tout en reconnaissant que cette vérité reste soumise à révision. ===== Les défis majeurs de la théorie ===== '''Le risque de confusion entre utilité et vérité''' L’objection classique, formulée notamment par G. E. Moore et Bertrand Russell, est que l’utilité n’est pas la même chose que la vérité. Une croyance peut être extrêmement utile sans être vraie. Un mensonge consolateur peut apporter du réconfort. Une superstition peut sembler « marcher » pendant un certain temps. À l’inverse, une vérité peut être douloureuse, socialement coûteuse et, à court terme, peu « utile ». Si le pragmatisme identifie purement et simplement la vérité à l’utilité, il semble commettre une confusion : la relation logique entre ''être vrai'' et ''être utile'' n’est pas une identité. '''Le problème du relativisme pratique''' L’utilité est en partie relative : ce qui est utile pour une personne ne l’est pas forcément pour une autre ; ce qui est utile à court terme peut être désastreux à long terme. Si l’on définit la vérité par l’utilité, ne risque-t-on pas de se retrouver avec autant de « vérités » qu’il y a de contextes et d’intérêts ? La conception pragmatiste de la vérité ne conduit-elle pas à un relativisme général, voire à l’idée qu’il n’existe plus de vérité unique et objective ? '''Les propositions sans pertinence pratique apparente''' Une autre difficulté concerne les propositions qui ne semblent avoir aucune pertinence pratique concevable, du moins pour nous. Par exemple : « Il existe un nombre pair d’atomes dans la Lune. » Cette proposition ne joue aucun rôle dans notre action quotidienne, et peut-être ne jouera jamais un rôle pratique. Le pragmatisme paraît mal équipé pour rendre compte de ce type de vérités purement « spéculatives ». '''L’objection du décalage temporel''' Chez Peirce, la vérité est définie comme l’''opinion finale'' de l’enquête illimitée. Mais nous avons besoin de parler de vérité ici et maintenant. Comment pouvons-nous affirmer qu’une proposition est vraie aujourd’hui si sa vérité dépend, en principe, de ce que la communauté scientifique accepterait à la limite d’une enquête sans fin ? ===== Réponses élaborées par les pragmatistes ===== '''Distinguer utilité apparente et succès durable''' Les pragmatistes répliquent que leurs critiques confondent ''utilité momentanée ou apparente'' et ''succès durable'' dans l’expérience. Pour James, une croyance n’est véritablement « utile » — et donc légitimement qualifiée de vraie — que si elle continue à fonctionner au fil du temps, si elle résiste aux confrontations répétées avec la réalité. Une croyance illusoire peut procurer un avantage psychologique immédiat, mais elle finit, tôt ou tard, par échouer face aux faits. '''Le pragmatisme et l’objectivité''' Les pragmatistes insistent également sur le fait que leur position n’implique pas un relativisme sans frein. Peirce, en particulier, met l’accent sur la ''contrainte'' exercée par la réalité : ce n’est pas nous qui décidons arbitrairement de ce qui marchera ou non. Les échecs pratiques répétés, les réfutations expérimentales, les résistances du monde réel orientent progressivement l’enquête vers des croyances plus adéquates. Il n’y a pas une infinité de « vérités » possibles : il n’existe, en principe, qu’une seule opinion finale vers laquelle l’enquête idéale convergerait. '''L’importance du contexte sans relativisme total''' Reconnaître que la signification de certaines questions dépend d’un contexte pratique ne revient pas à dire que tout se vaut. Certaines questions ne deviennent pertinentes que dans des circonstances déterminées ; d’autres n’ont aucun intérêt pratique pour nous. Mais cela ne signifie pas qu’il n’existe plus de contraintes objectives : les contextes changent, la réalité, elle, ne dépend pas de nos caprices. ===== Variantes contemporaines du pragmatisme ===== '''Pragmatisme épistémique moderne''' Des auteurs contemporains ont développé des formes plus nuancées de pragmatisme, en particulier dans l’épistémologie. Sous l’étiquette de ''pragmatic encroachment'', certains (par exemple Jeremy Fantl, Matthew McGrath, John Hawthorne ou Jason Stanley) soutiennent que des facteurs pratiques — ce qui est en jeu pour le sujet — peuvent légitimement influer sur ce qui compte comme ''savoir'' dans un contexte donné, sans pour autant réduire la vérité elle-même à l’utilité. La structure pratique de la situation modifie les exigences épistémiques, non le sens du mot « vrai ». '''Synthèses avec les approches déflationnistes''' D’autres tentent de combiner le pragmatisme avec des théories déflationnistes de la vérité. L’idée est que le concept de vérité n’a peut-être pas une « essence » métaphysique profonde, mais joue néanmoins un rôle indispensable dans nos pratiques : dire qu’une proposition est vraie, c’est principalement marquer qu’elle est acceptable, qu’elle est confirmée, qu’on peut raisonnablement s’y fier dans l’action. ===== Conclusion : le pragmatisme comme intuition durable ===== Le pragmatisme demeure une perspective très influente pour qui cherche à penser la vérité à partir de la pratique humaine et scientifique. Il met l’accent sur le rôle de l’enquête, sur la dimension expérimentale de la connaissance, sur le lien intime entre croire vrai et pouvoir agir avec succès. Cependant, l’identification directe de la vérité à l’utilité paraît excessive. Nous gardons l’intuition tenace que certaines choses peuvent être vraies même sans être utiles, et que certaines croyances peuvent nous être utiles tout en étant fausses. La vérité semble posséder une dimension d’objectivité et de stabilité que l’efficacité pratique, à elle seule, ne suffit pas à capturer. La conclusion la plus raisonnable est peut-être que le pragmatisme met le doigt sur un aspect essentiel de la vérité : une proposition qui ne fait aucune différence dans l’expérience et l’action perd une grande part de son sens ; mais ce n’est qu’un aspect. Une théorie adéquate de la vérité devrait intégrer les intuitions pragmatistes — le rôle de l’enquête, de l’action, du succès pratique — tout en préservant l’idée que la vérité ne se réduit pas entièrement à ce qui nous est, ici et maintenant, utile. ==== 2.4 Théories déflationnistes et minimalistes ==== ===== Introduction : réduire la vérité à (presque) rien ===== Si les théories précédentes (correspondance, cohérence, pragmatisme) tentent chacune d'expliquer ''ce qu'est'' la vérité — en quoi elle consiste, quelle en serait la « nature » — les théories déflationnistes adoptent une attitude très différente : selon elles, '''il n’y a presque rien de profond à expliquer'''. La vérité n'est pas une propriété substantielle dotée d'une essence métaphysique ; c'est un concept mince, fait de platitudes, un simple outil linguistique régi par quelques règles d'usage. Dire d’une proposition qu’elle est vraie revient, pour l’essentiel, à réaffirmer cette proposition, sans lui ajouter un contenu conceptuel supplémentaire. Cette famille de positions rassemble plusieurs variantes : la théorie de la redondance (Frege, Ramsey), les théories disquotationnelles, le minimalisme de Paul Horwich, ainsi que des approches connexes comme le ''prosententialisme'' de Dorothy Grover. Toutes partagent une intuition commune : la philosophie en a trop demandé au concept de vérité ; il est temps de reconnaître sa pauvreté ontologique et sa simplicité conceptuelle. ===== Les origines : de Frege à Ramsey ===== '''Gottlob Frege et l’idée de superfluité''' Gottlob Frege, dans « La Pensée » (''Der Gedanke''), souligne un trait décisif : du point de vue du contenu de pensée, '''ajouter le prédicat ''vrai'' ne change rien'''. Dire « Il est vrai que la neige est blanche » ne fait, quant au contenu, que répéter « La neige est blanche ». Frege remarque d’ailleurs que, dans l’usage ordinaire, nous évitons en général d’ajouter « il est vrai que… » précisément parce que c’est superflu. Important toutefois : Frege n’est pas lui-même un déflationniste radical. Dans sa théorie logique, la vérité joue un rôle fondamental (le ''Vrai'' comme valeur de référence des énoncés). Mais son observation linguistique ouvre la voie à l’idée déflationniste : au niveau du discours, le prédicat « est vrai » semble, en grande partie, redondant. '''F. P. Ramsey et la théorie de la redondance''' Frank Plumpton Ramsey reprend et radicalise cette intuition dans la ''théorie de la redondance''. Selon lui, le mot ''vrai'' est '''logiquement superflu'''. La phrase « ''p'' est vraie » n’exprime rien de plus que la phrase « p ». Tout prédicat de vérité pourrait, en principe, être éliminé de notre langage sans perte de contenu cognitif. Ramsey illustre ce point sur des exemples simples : dire « Il est vrai que César a traversé le Rubicon » n’ajoute absolument rien à dire « César a traversé le Rubicon ». Le prédicat ''est vrai'' n’introduit ici aucun fait supplémentaire ; il se contente de reprendre la même affirmation sous une forme grammaticalement différente. Ramsey reconnaît cependant une '''utilité logique et pratique''' au prédicat de vérité, malgré sa redondance de contenu. Il sert notamment à formuler des ''généralisations aveugles'' (''blind generalizations''). Si je dis « Tout ce que le Pape a affirmé ex cathedra est vrai », j’endosse d’un seul coup une infinité de propositions dont je ne connais pas le détail. Sans le prédicat ''vrai'', je serais incapable de formuler cette généralisation d’un seul tenant. La vérité n’apporte donc pas de contenu supplémentaire, mais elle rend possible certains types d’énoncés. ===== Paul Horwich et le minimalisme ===== '''La théorie minimaliste contemporaine''' Paul Horwich, dans son ouvrage ''Truth'', propose une version systématique du déflationnisme qu’il appelle ''minimalisme''. Contrairement à Ramsey, Horwich admet que ''est vrai'' exprime bien une propriété, mais une propriété '''extrêmement mince''', dont la nature entière se laisse saisir par un simple schéma d’équivalence. Le cœur de sa théorie est le ''schéma d’équivalence'' (ou schéma T) : : « ''La proposition que P est vraie si et seulement si P''. » Chaque instance particulière de ce schéma, du type : : « ''La proposition que la neige est blanche est vraie si et seulement si la neige est blanche''. » est, pour Horwich, une platitude indéniable. Et c’est la '''totalité''' de ces platitudes — l’ensemble infini de toutes les instances du schéma — qui fixe entièrement le concept de vérité. Posséder le concept de vérité, c’est être disposé à accepter, pour toute proposition intelligible, l’instance correspondante du schéma T. Le minimalisme est ainsi une théorie ''implicite'' : il ne donne pas une définition explicite de ''vrai'', mais soutient que cette infinité d’équivalences suffit à capturer tout ce qu’il y a à dire de substantiel sur la vérité. '''Une propriété sans essence profonde''' Horwich insiste : si la vérité est bien une propriété (il y a un prédicat, et nous pouvons quantifier sur « les choses vraies »), '''elle ne possède pas pour autant d’« essence » riche'''. Il n’existe ni mécanisme caché de correspondance, ni structure de cohérence, ni critère pragmatique profond. Tout ce qu’il y a à dire sur la vérité se trouve déjà contenu dans ces équivalences « La proposition que P est vraie si et seulement si P ». La vérité ne joue donc aucun rôle explicatif autonome : elle ne vient pas s’ajouter, comme une cause ou un mécanisme, au fait que les choses se passent d’une certaine manière. Dire « La théorie fonctionne parce qu’elle est vraie » n’ajoute, pour Horwich, rien de plus que répéter : « La théorie fonctionne parce que les choses sont comme elle le dit. » '''La fonction pragmatique du prédicat de vérité''' Horwich reprend et systématise l’idée des généralisations aveugles. Le prédicat ''est vrai'' a, selon lui, '''un rôle logique et pragmatique très utile''' : il nous permet de parler de propositions que nous ne pouvons pas (ou pas aisément) énumérer une par une. Si je dis : « Tout ce que Jean a dit au tribunal est vrai », je ne connais pas forcément toutes ses phrases. Je ne peux donc pas les répéter. Le prédicat ''est vrai'' me permet, en un seul geste linguistique, de ratifier l’ensemble de ces énoncés. Il n’ajoute aucun fait de plus au monde ; il organise simplement notre discours de manière plus souple. ===== Autres variantes du déflationnisme ===== '''La théorie prosententielle de Dorothy Grover''' Dorothy Grover (avec Camp et Belnap) propose une version déflationniste originale : le ''prosententialisme''. L’idée est que les expressions comme « c’est vrai » ne fonctionnent pas comme un prédicat ordinaire appliqué à un objet (la proposition), mais comme des '''''prophrases''''' (ou ''prosentences''), analogues, pour les phrases, à ce que sont les pronoms pour les noms. Un pronom comme « il » renvoie à un nom mentionné auparavant. De même, une prosentence comme « c’est vrai » reprend une phrase énoncée plus haut dans le discours. Par exemple : : Jean : « Il pleut. » : Marie : « C’est vrai. » Ici, « C’est vrai » ne dit pas autre chose que « Il pleut ». Elle se contente de reprendre, sous forme anaphorique, la phrase précédente. Le mot ''vrai'' ne désigne alors aucune propriété mystérieuse ; il sert simplement à reconstruire, de manière abrégée, la phrase déjà énoncée. '''Le disquotationalisme de Quine''' Willard Van Orman Quine, lisant la théorie tarskienne de la vérité, développe une approche dite ''disquotationnelle''. L’idée centrale est que '''dire qu’une phrase est vraie revient à supprimer les guillemets''' qui en font un objet de discours : : « ''« La neige est blanche » est vraie si et seulement si la neige est blanche''. » Attribuer la vérité à « La neige est blanche », c’est tout simplement « enlever les guillemets » et affirmer « La neige est blanche ». Le prédicat de vérité fonctionne alors comme un mécanisme de ''déquotation'' permettant de passer du niveau du métalangage (où l’on parle des phrases) au niveau du langage-objet (où l’on affirme ces phrases). Quine voit là l’essentiel de la notion de vérité : un outil qui permet de formuler les schémas de Tarski (du type ''« p » est vraie si et seulement si p''), de quantifier sur les phrases, et de manipuler le langage dans le langage, sans charge métaphysique supplémentaire. ===== Avantages des théories déflationnistes ===== '''Parcimonie métaphysique''' Les théories déflationnistes sont extrêmement économes sur le plan ontologique. Elles n’ont pas besoin de postuler des « faits » spéciaux, des relations de correspondance mystérieuses, ni des structures de cohérence profondes. La vérité ne renvoie à aucun ingrédient supplémentaire dans la constitution du monde ; elle n’introduit pas de nouvelle catégorie d’entités. De ce point de vue, le déflationnisme apparaît comme une manière de répondre à la question « Qu’est-ce que la vérité ? » en dissolvant la tentation métaphysique plutôt qu’en proposant un nouvel étage d’explication. '''Fidélité à certaines platitudes ordinaires''' Le déflationnisme rend bien compte d’une intuition vernaculaire : dans bien des contextes, dire « il est vrai que p » n’ajoute rien d’autre que la force d’insistance. Dans une conversation ordinaire, répondre « C’est vrai » au lieu de répéter la phrase de l’interlocuteur ne semble pas faire intervenir un concept mystérieux ; c’est simplement une manière de reprendre et d’approuver ce qui vient d’être dit. Le schéma minimaliste « ''« p » est vraie si et seulement si p'' » paraît, à première vue, capter toute cette dimension banale du concept de vérité. '''Unification conceptuelle''' Enfin, le déflationnisme offre une image '''unifiée''' du concept de vérité à travers les domaines. Il n’a pas besoin d’expliquer différemment ce qui rend vraies les propositions scientifiques, morales, mathématiques, etc. Dans tous les cas, dire qu’une phrase est vraie, c’est seulement dire que les choses sont comme la phrase le dit. La diversité des domaines se joue dans le contenu de ''p'', non dans une nature variable de la vérité. ===== Les défis majeurs du déflationnisme ===== '''Le problème explicatif''' Une objection récurrente soutient que le déflationnisme '''affaiblit excessivement la capacité explicative''' de la notion de vérité. Dans la pratique scientifique, nous avons l’impression de pouvoir dire : « Cette théorie réussit parce qu’elle est vraie » ; ou encore : « Ces observations confirment que notre description est vraie, et c’est pour cela qu’elle permet des prédictions fiables. » Si le terme ''vrai'' ne fait que répéter ''p'', le déflationniste semble obligé de paraphraser : « La théorie réussit parce que le monde est comme la théorie le décrit. » Mais nombre de philosophes considèrent que cette reformulation ne fait que déplacer le problème, plutôt que d’expliquer pourquoi la vérité joue un rôle si central dans nos explications de la réussite scientifique, de la fiabilité des témoignages, ou du succès des méthodes de recherche. L’enjeu est le suivant : si la vérité n’est qu’un dispositif linguistique, pourquoi semble-t-elle jouer un rôle aussi crucial dans nos explications à propos de la connaissance, de la science ou même de la morale ? '''Le problème normatif''' Michael Dummett et d’autres ont souligné une autre difficulté : la vérité semble '''normative'''. Il existe une norme épistémique fondamentale : « Vous devez viser à croire ce qui est vrai et à rejeter ce qui est faux. » Toute la pratique de l’enquête, du débat rationnel, de la preuve, semble structurée par cette norme. Or, si la vérité ne possède aucun contenu substantiel, si elle n’est qu’un outil de ré-énonciation et de généralisation, d’où vient cette normativité ? Pourquoi devrait-on s’y conformer, au-delà du simple fonctionnement grammatical du prédicat « est vrai » ? Le risque est que le déflationnisme réduise la vérité à un rouage syntaxique et ne parvienne plus à expliquer ce qui en fait une norme régulatrice de notre vie cognitive. '''Fausseté, erreur et dissymétrie''' Une difficulté connexe concerne la '''fausseté'''. Le déflationniste dira volontiers : « ''La proposition que P est fausse si et seulement si non-P''. » Mais la symétrie formelle entre vérité et fausseté masque peut-être une dissymétrie conceptuelle profonde : nous pensons la vérité comme ce à quoi la pensée doit tendre, et la fausseté comme ce qu’il faut éviter ou corriger. Si la vérité et la fausseté sont toutes deux réduites à de simples équivalences formelles, que devient cette dissymétrie ? Que devient la notion de ''se tromper'' ? Le déflationnisme doit alors expliquer comment l’erreur, la rectification, la critique — centrales dans la pratique scientifique et dans l’argumentation — peuvent être comprises sans une conception plus robuste du vrai et du faux. '''La question des contextes opaques''' Enfin, les schémas disquotationnels du type « ''« p » est vraie si et seulement si p'' » fonctionnent bien dans des contextes dits ''transparents''. Mais dans des contextes ''opaques'' (par exemple ceux qui impliquent des verbes d’attitude comme « croire », « espérer », « douter »), la substitution de ''« p » est vraie'' à ''p'' n’est pas toujours innocente. Dire « Jean croit que ''« la neige est blanche » est vraie'' » n’est pas exactement la même chose que dire « Jean croit que la neige est blanche ». La gestion de ces contextes intensionnels complique l’application naïve du schéma d’équivalence et oblige les déflationnistes à affiner leur analyse linguistique. ===== Réponses et raffinements déflationnistes ===== '''Explication superficielle vs explication de fond''' Les déflationnistes répondent en distinguant deux niveaux. Au niveau « de fond », la vérité ne joue aucun rôle explicatif : ce qui explique le succès d’une théorie, ce sont les mécanismes du monde, les relations causales, la structure des phénomènes. Dire « la théorie est vraie » n’ajoute rien à cette explication. Mais au niveau « superficiel » de nos pratiques ordinaires, il est parfaitement légitime de dire : « la théorie réussit parce qu’elle est vraie », comme une manière compacte de résumer que ses énoncés décrivent correctement la réalité. La vérité n’explique rien par elle-même, mais elle sert d’étiquette commode pour résumer un ensemble très complexe de relations entre la théorie et le monde. '''La norme de vérité comme reflet de notre pratique''' Horwich, notamment, soutient que la normativité épistémique ne vient pas d’une « essence » de la vérité, mais du rôle que joue ce concept dans nos pratiques discursives. Le fait que nous ayons institué la règle « croire ce qui est vrai » n’exige pas que ''vrai'' désigne une propriété métaphysiquement riche ; il suffit que ce prédicat occupe la place de ce que nous tendons à approuver, endosser, ratifier. Autrement dit, la force normative du vrai serait un sous-produit de notre organisation linguistique et sociale, non l’expression d’une nature métaphysique mystérieuse. '''Pluralisme et déflationnisme modéré''' Certains auteurs défendent des positions hybrides. Ils admettent que '''le concept ordinaire de vérité''' est en grande partie bien décrit par les schémas déflationnistes, tout en reconnaissant que, dans certains domaines (par exemple en métaphysique, en théologie ou en morale), nous utilisons aussi des notions plus épaisses, comme « adéquation à la réalité », « exactitude », « fidélité », etc. On obtient ainsi des formes de ''pluralisme'' : d’un côté, un noyau déflationniste permettant de traiter la vérité comme une notion logique commune à tous les discours ; de l’autre, des notions plus substantielles, propres à certains domaines, qui capturent des exigences supplémentaires (réalisme moral, réalisme scientifique, etc.). ===== Déflationnisme vs théories substantialistes : un clivage central ===== Le contraste entre les théories déflationnistes et les théories plus « riches » (correspondance, cohérence, pragmatisme) se laisse ramener à une question centrale : : '''La vérité possède-t-elle une nature positive qu’il faut analyser ?''' Les théories de la correspondance, de la cohérence ou du pragmatisme répondent : oui. La vérité est, selon les cas, un rapport de correspondance à la réalité, un état de cohérence au sein d’un système de croyances, ou un succès pratique dans l’action. Le rôle de la théorie de la vérité est alors de mettre au jour cette nature et d’en éclairer les implications. Le déflationnisme, au contraire, répond : non. Il n’existe rien de plus dans la vérité que ces platitudes capturées par le schéma d’équivalence. Chercher une « essence » de la vérité, c’est projeter sur ce concept des attentes métaphysiques excessives. La tâche philosophique, ici, est moins d’expliquer la vérité que de dissoudre l’illusion selon laquelle il y aurait quelque chose de profond à expliquer. ===== Conclusion : la minimalité provocante du déflationnisme ===== Le déflationnisme présente la vérité comme un concept '''minimal''', presque squelettique, et c’est précisément ce minimalisme qui le rend philosophiquement provocateur. En refusant d’attribuer à la vérité une nature métaphysique riche — des faits de correspondance, des structures de cohérence, des critères pragmatiques — il met en question une grande part de la tradition. En même temps, cette austérité laisse un sentiment d’inachèvement. Si la vérité n’est vraiment rien d’autre que ce que dit le schéma « ''« p » est vraie si et seulement si p'' », comment rendre justice au rôle qu’elle joue dans la science, dans la critique, dans l’éthique de la croyance, dans les conflits politiques où l’on se bat précisément au nom de la vérité ? Le déflationnisme peut répondre que ce rôle tient aux contenus mêmes des propositions, aux pratiques sociales, aux structures du monde, non à la vérité comme telle. Beaucoup de philosophes, toutefois, trouvent cette dissolution insatisfaisante. Qu’on l’adopte ou qu’on le rejette, le déflationnisme a une vertu théorique incontestable : il oblige les défenseurs de théories plus substantielles à justifier '''pourquoi''' la vérité devrait être autre chose qu’un schéma d’équivalence apparemment trivial. En ce sens au moins, la position déflationniste constitue une contribution durable au débat contemporain sur la nature — ou la non-nature — de la vérité. ==== 2.5 Théories épistémiques de la vérité ==== ===== Introduction : la vérité au service de la connaissance ===== Les théories épistémiques de la vérité proposent un renversement conceptuel par rapport aux approches plus classiques. Au lieu de définir d’abord la vérité de manière indépendante (par exemple comme correspondance, cohérence ou utilité), puis de se demander ensuite comment elle se rapporte à la connaissance, elles soutiennent que '''la vérité ne peut être comprise qu’en la rapportant dès l’origine à des notions épistémiques telles que la connaissance, la justification, la vérification ou l’acceptabilité rationnelle'''. Autrement dit, la vérité n’est pas conçue comme une propriété métaphysique flottant au-dessus de nos pratiques cognitives, mais comme une notion dont le sens est indissociable de ce que nous faisons lorsque nous enquêtons, justifions, vérifions, acceptons ou rejetons des énoncés. Sous l’étiquette de ''théories épistémiques'', on regroupe plusieurs familles d’approches, qui ne sont pas toutes, au sens strict, des « théories de la vérité », mais qui accordent à la vérité un rôle central à l’intérieur de l’épistémologie : le ''vérificationnisme'' (la vérité pensée à partir de la vérification possible), les perspectives relativistes ou perspectivistes (la vérité envisagée relativement à un cadre conceptuel ou culturel), les conceptions ''véristes'' (''veritism'') qui font de la vérité le bien épistémique fondamental, et les approches dites de la ''connaissance d’abord'' (''knowledge-first''), qui assignent à la connaissance un rôle premier, la vérité étant intégrée à cette notion. ===== Le vérificationnisme ===== '''La conception classique : vérification et sens''' Le vérificationnisme soutient, dans son noyau le plus simple, que la vérité d’une proposition dépend de sa vérifiabilité : '''une proposition n’est véritablement candidate à la vérité que si elle est, au moins en principe, vérifiable'''. Historiquement, cette idée est étroitement liée au positivisme logique du Cercle de Vienne au XX{{e}} siècle. Les positivistes logiques formulent d’abord un '''principe de vérification du sens''' : un énoncé n’a de contenu cognitif que si l’on peut, au moins en principe, indiquer quelles expériences possibles compteraient comme sa confirmation ou sa réfutation. Les énoncés strictement métaphysiques ou théologiques, qui ne semblent pas susceptibles d’être confirmés ou infirmés par l’expérience, sont dès lors réputés dépourvus de véritable signification cognitive. On ne dira pas tant qu’ils sont faux que qu’ils ne disent rien de déterminé sur le monde. Dans ce cadre, la vérité elle-même tend à être pensée à travers la vérification : dire qu’un énoncé est vrai revient à dire qu’il est, en principe, vérifiable et qu’il résisterait idéalement à toutes les épreuves empiriques pertinentes. La vérité n’est plus un état de choses mystérieux situé « au-delà » de nos moyens de connaissance ; elle est ce vers quoi convergerait, en droit, une enquête pleinement informée. '''Variantes du vérificationnisme''' On distingue classiquement plusieurs formes de vérificationnisme, plus ou moins exigeantes. Une forme '''forte''' exige que la proposition soit vérifiable avec certitude. Interprétée de manière rigide, cette thèse s’avère rapidement intenable : très peu d’énoncés scientifiques satisfont un tel critère de vérification définitive. C’est l’une des raisons qui ont conduit à l’abandon du vérificationnisme fort. Une forme '''faible''' affirme plutôt qu’un énoncé est doué de sens et peut être vrai ou faux si l’on peut spécifier, au moins en principe, les conditions dans lesquelles il serait confirmé ou infirmé par l’expérience. On ne demande plus une vérification complète et définitive, mais la possibilité de construire un lien intelligible entre l’énoncé et l’expérience. Enfin, une forme '''probabiliste''' intègre explicitement le ''fallibilisme''. La vérification ne fournit jamais une certitude absolue, mais confère à nos énoncés des degrés de confirmation. Dans cette perspective, la « vérité » d’une proposition est intimement liée au degré de soutien que lui apporte l’évidence empirique disponible, tel que modélisé, par exemple, dans des cadres bayésiens. Le vérificationnisme a cependant rencontré des objections décisives : difficulté à formuler un critère de vérification qui n’auto-réfute pas lui-même, tendance à exclure du domaine du sens des énoncés que l’on hésite à considérer comme dépourvus de signification (évaluations morales, énoncés d’énorme portée cosmologique, etc.). De ce fait, il a été largement abandonné dans sa forme la plus dogmatique, mais il reste important comme tentative de rapprocher aussi étroitement que possible la vérité, le sens et la possibilité de vérification. ===== Perspectivisme et relativisme épistémique ===== '''La vérité comme « vérité de quelque part »''' Une autre famille d’approches insiste sur le fait que '''nous n’accédons jamais à la vérité qu’à partir d’un point de vue déterminé : une perspective personnelle, culturelle, historique ou théorique'''. Le ''perspectivisme'' soutient que ce que nous appelons « la vérité » n’est jamais, dans la pratique, une vue de nulle part, mais toujours la vérité telle qu’elle apparaît à l’intérieur d’un cadre conceptuel donné. Dans une version modérée, on admet volontiers qu’il existe une réalité indépendante et que certaines propositions sont objectivement vraies, mais on souligne que notre accès à ces vérités est toujours médiatisé par des schèmes de pensée, des langages, des intérêts et des pratiques situés. On parlera alors de '''perspectivisme faible''' : la vérité n’est pas elle-même relative, mais notre rapport à la vérité l’est inévitablement. Dans une version plus radicale, parfois qualifiée de '''perspectivisme fort''' ou de '''relativisme de la vérité''', on soutient que la vérité elle-même ne transcende pas les perspectives. Dans cette optique, il n’existerait pas de vérité absolue valable pour tous, mais seulement des vérités « pour nous », « pour eux », « dans tel cadre scientifique », « dans telle culture ». Une même proposition pourrait être vraie relativement à un système de normes épistémiques et fausse relativement à un autre. Le '''relativisme culturel''' constitue une variante importante de cette famille : ce que l’on tient pour vrai dépendrait essentiellement des normes, des critères de preuve et des catégories conceptuelles propres à une culture donnée. Ainsi, les « vérités » cosmologiques, morales ou même médicales d’une société traditionnelle pourraient différer profondément de celles d’une société technoscientifique moderne, sans qu’il existe, selon ce point de vue, de tribunal neutre permettant de trancher entre elles. '''Objections majeures''' Ces approches rencontrent des difficultés sérieuses. La plus connue est l’objection d’auto-réfutation : si l’on affirme que « toute vérité est relative à une perspective », cette affirmation doit-elle, elle aussi, être tenue pour simplement relative ? Si elle ne vaut que pour certains, on ne voit pas pourquoi ceux qui rejettent le relativisme devraient s’y soumettre. Si, au contraire, elle prétend valoir absolument, elle dément son propre contenu. On semble pris dans une tension entre la portée universelle de la thèse et son refus de toute universalité. Une autre difficulté tient à la pratique même de la critique et du désaccord. Si des perspectives différentes sont, par principe, incommensurables, comment rendre intelligible le fait que nous confrontions des arguments, que nous révisions nos opinions, que nous cherchions à convaincre autrui ? Le risque est alors de dissoudre la notion même de vérité dans celle de simple acceptation locale, et de rendre énigmatique la possibilité d’un progrès cognitif réel. ===== Le vérisme : la vérité comme valeur épistémique fondamentale ===== '''La vérité comme bien épistémique premier''' Sous le nom de ''vérisme'' (''veritism'' dans la littérature anglophone), certains épistémologues défendent l’idée que '''la vérité est le bien épistémique fondamental : c’est la seule chose qui possède une valeur épistémique intrinsèque, non simplement instrumentale'''. Une croyance vraie est, en tant que telle, un état cognitif meilleur qu’une croyance fausse, indépendamment des avantages pratiques qu’elle peut procurer. Dans cette perspective, les autres biens épistémiques — justification, compréhension, sagesse, vertus intellectuelles — tirent leur valeur de leur relation à la vérité. Une croyance justifiée vaut mieux qu’une croyance non justifiée parce qu’elle est, en moyenne, plus proche de la vérité ; une vertu intellectuelle (comme la lucidité, la précision, l’honnêteté) vaut parce qu’elle nous dispose à former davantage de croyances vraies qu’un agent négligent, distrait ou malhonnête. On obtient ainsi une hiérarchie : au sommet, la vérité, comme bien épistémique ultime ; en dessous, les propriétés qui sont précieuses parce qu’elles nous rapprochent de la vérité (justification, fiabilité, vertus intellectuelles) ; enfin, des biens dérivés comme la compréhension ou la sagesse, qui supposent un large ensemble de croyances vraies organisées de manière intelligible. '''Le « problème de la submersion »''' Le vérisme se heurte cependant à un problème célèbre, souvent appelé ''problème de la submersion'' (''swamping problem''). Si la seule source de valeur épistémique est la vérité, comment expliquer que nous valorisions aussi la justification et les vertus intellectuelles, une fois que la vérité est acquise ? En effet, si l’on compare deux croyances également vraies, l’une solidement justifiée, l’autre vraie par pur hasard, le vériste semble contraint de dire que, du point de vue de la valeur épistémique pure, elles se valent : dans les deux cas, nous possédons la vérité, qui est le seul bien non instrumental. Or nous avons l’intuition nette que la croyance vraie bien justifiée vaut mieux que la croyance vraie fortuite. Il semble alors que la justification et les vertus intellectuelles possèdent une valeur qui ne se laisse pas entièrement réduire à leur rôle instrumental au service de la vérité. Une autre difficulté concerne certaines vertus intellectuelles comme l’ouverture d’esprit ou la disposition à remettre en question des convictions établies. Elles peuvent, à court terme, nous éloigner de la vérité (en suspendant des croyances vraies que nous possédions déjà), tout en apparaissant pourtant comme épistémiquement souhaitables. Là encore, il semble que la valeur épistémique ne se laisse pas ramener intégralement à la seule possession de croyances vraies. ===== L’approche de la « connaissance d’abord » (''knowledge-first'') ===== '''La primauté de la connaissance sur la vérité et la justification''' Plus récemment, certaines épistémologies dites de la '''« connaissance d’abord »''' (''knowledge-first epistemology'') ont proposé un déplacement encore plus radical : '''la notion épistémique fondamentale ne serait ni la vérité ni la justification, mais la connaissance elle-même'''. Dans cette approche, illustrée notamment par les travaux de Timothy Williamson, la connaissance n’est plus analysée comme croyance vraie justifiée ; au contraire, ce sont la croyance, la justification ou même le concept de vérité épistémique qui doivent être expliqués à partir de la connaissance. La connaissance y est conçue comme un état mental factif : savoir que p implique nécessairement que p est vrai, mais la connaissance n’est pas pour autant réductible à la simple conjonction ''croyance + vérité''. Elle possède une structure propre, irréductible à ces deux éléments pris séparément. L’épistémologie ne cherche plus prioritairement une « définition » de la connaissance ; elle se demande plutôt quelles lois, quelles normes et quelles structures conceptuelles régissent cet état mental fondamental. '''La connaissance comme norme et comme but de l’enquête''' Les épistémologies ''knowledge-first'' mettent en avant le rôle normatif de la connaissance : – en matière d’assertion, la norme la plus exigeante énonce que l’on ne devrait affirmer que ce que l’on sait ;<br> – en matière de raisonnement, on ne devrait utiliser comme prémisses que des propositions que l’on sait vraies ;<br> – en matière d’action, on devrait agir sur la base de ce que l’on sait, plutôt que sur de simples conjectures. La connaissance apparaît alors comme le critère de ce que nous sommes en droit d’affirmer, de supposer, d’utiliser comme base de décision. Elle est aussi présentée comme le '''but propre de l’enquête cognitive''' : ce que nous visons, dans la recherche scientifique comme dans la vie quotidienne, n’est pas seulement la croyance vraie, mais la croyance vraie suffisamment bien ancrée pour mériter le nom de connaissance. Dans ce cadre, la vérité conserve un rôle essentiel (puisque la connaissance est factive), mais elle est intégrée à une notion plus riche : on ne définit pas la connaissance à partir de la vérité ; c’est l’inverse, la vérité épistémiquement pertinente est celle qui s’inscrit dans les états de connaissance. ===== Connexions entre vérité et justification : le fiabilisme ===== '''La question de fond : la justification rapproche-t-elle de la vérité ?''' Toutes ces approches épistémiques rencontrent une question commune : '''dans quelle mesure la justification est-elle réellement liée à la vérité ?''' Si la justification ne faisait que refléter les normes internes d’une communauté, sans aucune connexion fiable à la réalité, elle perdrait sa valeur épistémique. Inversement, si l’on suppose qu’elle est en général un bon indicateur de la vérité, il faut expliquer en quoi consiste ce lien. Le ''fiabilisme'' (''reliabilism'') propose une réponse influente. Une croyance est justifiée, ou constitue une connaissance, si elle est produite par un processus cognitif globalement fiable, c’est-à-dire qui conduit, dans une proportion suffisamment élevée de cas, à des croyances vraies : perception sensorielle dans des conditions normales, mémoire saine, inférences déductives valides, etc. La justification n’est plus définie par ce que le sujet peut « voir » de l’intérieur de sa propre conscience, mais par la qualité objective des mécanismes par lesquels il forme ses croyances. Le fiabilisme établit ainsi un lien direct entre justification et vérité : ce qui rend une méthode de formation de croyance justifiée, c’est précisément sa tendance à produire de la vérité plutôt que de l’erreur. Il s’agit d’un lien non pas logique (une croyance justifiée peut toujours, en principe, être fausse), mais statistique et causal : un agent dont les facultés cognitives sont globalement fiables sera, dans l’ensemble, plus souvent dans le vrai que dans le faux. Cette approche est typiquement ''externaliste'' : le sujet peut ignorer les détails de ce qui rend ses processus fiables, sans pour autant perdre sa justification. Elle offre une manière particulièrement claire d’illustrer la manière dont une théorie épistémique peut tenter de faire de la vérité la norme et le critère de nos pratiques justificatrices. ===== Avantages des théories épistémiques ===== Les théories épistémiques de la vérité, au sens large, ont le mérite de rappeler que '''la vérité n’est pas un concept isolé des pratiques réelles de la connaissance'''. Elles soulignent que nous nous intéressons à la vérité parce qu’elle est intimement liée à des questions de justification, d’enquête, de décision, de coordination sociale, d’action rationnelle. La vérité n’est pas seulement un idéal abstrait ; elle est ce que nous cherchons lorsque nous menons une enquête, lorsque nous confrontons nos arguments, lorsque nous corrigeons nos erreurs. Elles ont aussi l’avantage d’intégrer de façon organique la théorie de la vérité à l’épistémologie : au lieu de traiter séparément, dans des chapitres distincts, la vérité d’un côté, la justification de l’autre, la connaissance ailleurs, elles insistent sur l’imbrication conceptuelle de ces notions et cherchent à les penser ensemble. ===== Problèmes majeurs des approches épistémiques ===== Ces approches ne sont cependant pas exemptes de difficultés. D’abord, elles risquent de '''tourner en rond'''. Si l’on définit la vérité en termes de vérifiabilité, d’acceptabilité rationnelle idéale ou de convergence de l’enquête, et que l’on définit ensuite la connaissance ou la justification comme des moyens fiables d’atteindre la vérité, on semble pris dans une circularité. On utilise la vérité pour définir les bons processus épistémiques, mais l’on utilise ces mêmes processus pour définir ce qu’est la vérité « épistémiquement ». La frontière entre connexion profonde et redéfinition circulaire devient difficile à tracer. Ensuite, certaines de ces théories encourent le reproche de '''relativisme ou de psychologisme''' : si la vérité est définie par ce que certaines personnes acceptent, jugent rationnel ou trouvent vérifiable, ne risque-t-on pas de réduire la vérité à un état psychologique collectif, variable d’une communauté à l’autre ? Comment préserver alors l’idée d’une vérité qui puisse résister à nos convictions, qui puisse « faire démentir » une communauté entière ? Enfin, les versions vérificationnistes classiques se heurtent à des difficultés bien connues : leur propre principe de vérification paraît lui-même invérifiable par l’expérience ; elles ont tendance à exclure du domaine du sens des types d’énoncés que l’on hésite à déclarer insignifiants ; elles sous-estiment la possibilité de vérités qui dépassent pour longtemps nos capacités actuelles de vérification, sans être pour autant dépourvues de sens. ===== Réponses contemporaines et position équilibrée ===== Les défenseurs contemporains d’approches épistémiques tendent à nuancer fortement les thèses les plus ambitieuses du passé. Plutôt que de prétendre '''réduire''' la vérité à des notions épistémiques, beaucoup se contentent de souligner une '''connexion constitutive''' : la vérité reste une propriété objective des énoncés, mais notre compréhension de ce qu’elle est et de la manière dont elle se manifeste passe nécessairement par l’analyse de nos pratiques de justification, de vérification, de discussion, de correction des erreurs. Certains adoptent un '''pluralisme épistémique modéré''' : la vérité, la connaissance, la justification, la compréhension, les vertus intellectuelles sont autant de biens épistémiques qui se soutiennent mutuellement sans se réduire entièrement les uns aux autres. La vérité conserve un statut central, mais elle n’épuise pas à elle seule tout ce qui compte dans la vie de l’esprit. ===== Conclusion : la vérité inséparable de l’épistémologie ===== Les théories épistémiques de la vérité, malgré leurs désaccords internes et leurs limites, expriment une intuition profonde : '''on ne peut pas comprendre pleinement ce qu’est la vérité sans tenir compte de ce que nous faisons lorsque nous cherchons à savoir'''. La vérité n’est pas seulement un rapport mystérieux entre des propositions et un monde entièrement extérieur à nos pratiques ; elle est aussi ce vers quoi tendent nos enquêtes, ce qui oriente nos normes de justification, ce qui donne sens à nos efforts pour distinguer le savoir de l’illusion. Même si l’on refuse de définir la vérité exclusivement en termes épistémiques, on est conduit à reconnaître que vérité, justification et connaissance forment un réseau conceptuel étroitement solidaire. C’est ce réseau que l’épistémologie contemporaine s’efforce de démêler, en prenant acte à la fois de l’objectivité de la vérité et du caractère inévitablement situé, faillible et révisable de nos accès humains à cette vérité. ==== 2.6 Pluralisme et contextualisme alétiques ==== ===== Introduction : la multiplicité des formes de vérité ===== Alors que les théories examinées jusqu’ici cherchent, chacune à leur manière, à proposer une explication ''unique'' de la vérité valable pour tout type d’énoncé, le pluralisme alétique introduit une rupture profonde : '''il n’existe pas une seule et même nature de la vérité, mais plusieurs ''propriétés de vérité'' distinctes, pertinentes selon les différents domaines de discours'''. À cette thèse s’ajoute le contextualisme alétique, qui soutient que '''la vérité d’une proposition peut dépendre de manière systématique du contexte dans lequel elle est formulée'''. Au lieu de supposer qu’une seule théorie moniste de la vérité doit s’appliquer indistinctement au discours scientifique, mathématique, moral, juridique ou esthétique, le pluralisme admet que les critères de vérité varient légitimement selon les domaines de connaissance. Le contextualisme, de son côté, souligne que même au sein d’un domaine donné, les conditions de vérité d’une proposition peuvent être sensibles à des paramètres contextuels (par exemple les enjeux pratiques, les présupposés communs, le niveau d’exigence épistémique). Ces approches, développées notamment par Crispin Wright et Michael P. Lynch, entendent répondre à plusieurs difficultés classiques de la théorie de la vérité : le ''problème de portée'' (comment une seule théorie pourrait-elle s’appliquer uniformément à tous les types d’énoncés ?), le ''problème des inférences mixtes'' (comment valider les inférences qui combinent des énoncés appartenant à des domaines hétérogènes ?) et, plus indirectement, certains ''paradoxes sémantiques'' (comme le paradoxe du menteur), qui semblent mettre à l’épreuve les conceptions monistes trop rigides. ===== Le pluralisme alétique : principes de base ===== Le pluralisme alétique commence par rejeter le ''monisme alétique'', c’est-à-dire la thèse selon laquelle il existerait '''une unique propriété de vérité''' commune à toutes les propositions vraies, quelle que soit leur nature. Selon le moniste, un énoncé empirique de physique (« La pression augmente avec la température, toutes choses égales par ailleurs »), un théorème mathématique (« Deux plus deux égale quatre ») ou un jugement moral (« Cette action est injuste ») sont vrais au sens d’une seule et même propriété — par exemple la correspondance avec les faits, ou la cohérence avec un système de croyances, etc. Le pluraliste observe au contraire que les grandes théories monistes de la vérité semblent particulièrement adaptées à certains champs, et nettement moins à d’autres. La théorie de la correspondance paraît convenir de manière naturelle aux énoncés empiriques portant sur des faits observables : il est assez intuitif de dire que « La neige est blanche » est vraie parce qu’il existe un état de choses dans le monde — la blancheur de la neige — auquel l’énoncé correspond. Mais cette même notion de correspondance devient plus obscure quand on l’applique à des énoncés mathématiques (« Deux plus deux égale quatre ») ou à des vérités logiques, qui ne semblent pas décrire un ''état de choses'' au sens ordinaire. À l’inverse, une théorie de type cohérentiste paraît rendre mieux compte de la vérité en mathématiques ou en logique (où l’enjeu est la place d’un énoncé dans un système démonstratif), mais elle paraît insuffisante pour les énoncés empiriques élémentaires, dont la vérité ne dépend pas uniquement des relations internes à un système de propositions. À partir de ce constat, le pluralisme alétique soutient qu’il faut '''admettre la pluralité des propriétés de vérité'''. La vérité des énoncés empiriques pourrait reposer principalement sur une relation de correspondance à la réalité ; celle des énoncés mathématiques, sur des critères de cohérence, de démontrabilité ou de nécessité logique ; celle de certains jugements évaluatifs, sur des formes d’acceptabilité rationnelle dans des conditions idéales ou sur des critères de justification pratique. L’idée générale n’est pas que chaque domaine soit totalement fermé aux autres, mais que la propriété qui ''réalise'' la vérité n’est pas la même partout, même si nous utilisons partout le même mot « vrai ». On distingue souvent, à l’intérieur du pluralisme alétique, deux versions : D’un côté, un '''pluralisme radical''' affirme qu’il n’existe aucune propriété de vérité commune à tous les domaines ; dans chaque champ, ''une'' propriété différente joue le rôle de vérité, et il n’y a entre elles qu’une parenté purement verbale. De l’autre, un '''pluralisme modéré''' soutient qu’il existe bien un concept général de vérité — une notion très « allégée » ou minimale — commun à tous les usages, mais que ce concept peut être ''réalisé'' par des propriétés différentes selon les domaines (correspondance ici, cohérence ou superassertibilité ailleurs, etc.). C’est cette forme modérée qui est aujourd’hui la plus largement défendue. ===== Crispin Wright et la ''superassertibilité'' ===== Crispin Wright est l’un des principaux artisans contemporains du pluralisme alétique. Il propose d’identifier ce qu’il y a de commun à tous les usages du mot « vrai » à une notion épistémique générale : la ''superassertibilité''. De façon très schématique, une proposition est dite ''superassertible'' si elle est actuellement assertible (c’est-à-dire si nous disposons de raisons suffisantes pour l’affirmer) et si cette assertibilité résisterait à toute amélioration possible de l’information et de l’enquête. Autrement dit, une proposition est vraie si elle pourrait être maintenue rationnellement dans le cadre d’une enquête idéale, où toutes les données pertinentes auraient été rassemblées et soumises à la critique. Cette notion de superassertibilité se veut ''minimale'' : elle ne présuppose pas, en elle-même, une métaphysique spécifique de la vérité (ni correspondance, ni cohérence, ni utilité). Elle décrit plutôt le rôle ''normatif'' que joue la vérité dans nos pratiques : être vrai, c’est être ce que l’on peut, en principe, affirmer de façon irrévocablement justifiée, quelles que soient les révisions et les corrections ultérieures de nos croyances. Wright propose par ailleurs une méthode dite des ''platitudes'' pour identifier, dans un domaine donné, la propriété qui joue effectivement le rôle de vérité. Les ''platitudes'' sont un ensemble de principes largement partagés à propos de la vérité, par exemple l’idée que : – une proposition vraie est, en un sens, « correcte » indépendamment du fait qu’on y croie ou non ;<br> – la vérité est en général l’objectif de la croyance et de l’enquête ;<br> – il n’est pas possible, dans un même contexte, qu’une proposition et sa négation soient toutes deux vraies ;<br> – la vérité est stable sous l’extension de l’enquête : si une proposition est vraie, l’accumulation de nouvelles preuves ne devrait pas, en principe, la faire passer au faux. Dans chaque domaine, on examine alors quelle propriété (correspondance, cohérence, superassertibilité, acceptabilité idéale, etc.) satisfait le mieux ce faisceau de platitudes. Celle qui remplit ce rôle ''dans ce domaine-là'' mérite alors d’être appelée la ''propriété de vérité'' propre au domaine considéré, tout en restant compatible avec la notion générale de superassertibilité comme concept minimal. ===== Michael Lynch et le ''fonctionnalisme alétique'' ===== Michael P. Lynch prolonge et systématise cette intuition en défendant un ''fonctionnalisme alétique''. Au lieu de chercher une unique propriété métaphysique de la vérité, Lynch propose d’identifier la vérité à un ''rôle fonctionnel'' : la vérité est ce qui remplit, dans nos pratiques cognitives, une certaine fonction caractéristique. De manière simplifiée, cette fonction consiste à servir de norme générale pour la croyance, à permettre que nos jugements soient évalués, révisés et justifiés en fonction de la manière dont ils se rapportent au réel (ou, dans certains domaines, à des structures rationnelles plus abstraites). Lynch soutient ainsi qu’il peut exister plusieurs propriétés métaphysiquement différentes qui ''réalisent'' ce rôle fonctionnel de la vérité dans des domaines distincts, tout comme, en philosophie de l’esprit, différents états neurophysiologiques peuvent réaliser le même état mental fonctionnel. Ce qui assure l’unité du concept de vérité n’est donc pas l’identité d’une propriété unique, mais l’identité du ''rôle'' joué par ces différentes propriétés : être vrai, c’est, en tout domaine, occuper cette place de norme ultime de correction pour les croyances. Ce fonctionnalisme alétique permet de concilier la diversité réelle des critères de vérité (pluralisme) avec une certaine unité conceptuelle (un seul concept fonctionnel de vérité), sans réduire la vérité à une seule de ses réalisations possibles (par exemple la correspondance). ===== Le contextualisme alétique ===== Le contextualisme alétique met l’accent non plus sur la multiplicité des propriétés de vérité entre domaines, mais sur la '''sensibilité au contexte''' des conditions de vérité d’un énoncé. L’idée générale est que ce qui compte comme vrai ou faux peut dépendre de paramètres contextuels : qui parle, à qui, dans quelles circonstances, avec quels présupposés partagés et quels enjeux pratiques. Un exemple simple est celui d’énoncés évaluatifs comme « C’est difficile » ou « Il fait froid ». Dire « Ce problème est difficile » peut être vrai dans le contexte d’un enfant de sept ans qui découvre l’addition, et faux dans le contexte d’un mathématicien professionnel pour qui la même tâche est trivialement facile. Le contenu précis de l’énoncé, et donc ses conditions de vérité, varient avec le contexte de prononciation, même si la phrase utilisée reste la même. Dans la littérature analytique, le contextualisme a été d’abord développé à propos de la connaissance (''knowledge contextualism'') : les standards de vérité des phrases de type « S sait que p » augmentent ou diminuent en fonction des exigences épistémiques du contexte (par exemple, selon que l’on discute dans un cadre ordinaire ou dans un séminaire sceptique où l’on soulève des scénarios de rêve ou de « cerveau dans une cuve »). On peut transposer cette idée à la vérité elle-même : dans certains contextes, des standards de correspondance très stricts sont requis ; dans d’autres, des critères plus relâchés ou plus pragmatiques suffisent. On peut distinguer, là encore, des formes plus ou moins fortes de contextualisme : – Dans une version '''modérée''', le contexte fixe les paramètres pertinents (qui est visé par « difficile », quel degré de précision est exigé, quelles alternatives sont prises en compte, etc.), puis, une fois ce cadre déterminé, la proposition ainsi ''contextualisée'' est, de façon objective, vraie ou fausse. Le contexte influe sur les conditions de vérité, non sur la nature même de la vérité. – Dans une version '''forte''', on va jusqu’à dire qu’une même phrase peut être ''vraie dans un contexte'' et ''fausse dans un autre'', sans que l’une de ces évaluations doive nécessairement l’emporter. La vérité est alors explicitement indexée aux contextes, au risque d’approcher une forme de relativisme alétique. Le contextualisme ne nie pas nécessairement l’existence d’une seule propriété de vérité ; il insiste plutôt sur le fait que les conditions d’application de cette propriété varient avec le contexte. Il est donc conceptuellement distinct du pluralisme, même si, dans la pratique, les deux perspectives peuvent se combiner. ===== Avantages du pluralisme et du contextualisme alétiques ===== Pluralisme et contextualisme présentent plusieurs atouts théoriques. D’abord, ils offrent une réponse convaincante au ''problème de portée''. Plutôt que d’exiger d’une seule théorie moniste qu’elle rende compte à la fois de la vérité des lois physiques, des théorèmes mathématiques, des jugements moraux, des appréciations esthétiques et des énoncés de droit, le pluralisme permet de reconnaître que des critères différents sont pertinents dans des domaines différents. Il n’est plus nécessaire de forcer, par exemple, les énoncés moraux à entrer dans le moule de la correspondance, ni les vérités mathématiques à celui de l’utilité pragmatique. Ensuite, le pluralisme éclaire rétrospectivement le succès partiel des grandes théories traditionnelles de la vérité. Si la correspondance, la cohérence, l’acceptabilité rationnelle ou l’efficacité pragmatique semblent chacune saisir une dimension authentique de la vérité, c’est peut-être parce qu’elles décrivent correctement ce qui se passe ''dans certains domaines particuliers''. Chacune serait alors une bonne théorie ''sectorielle'' de la vérité, sans qu’aucune ne puisse prétendre à l’exclusivité. Le contextualisme, de son côté, rend compte de la sensibilité manifeste de nos jugements de vérité au contexte. Il explique pourquoi certaines disputes apparaissent « purement verbales » : une même phrase peut être évaluée différemment parce que les interlocuteurs n’opèrent pas, de fait, avec les mêmes paramètres contextuels. En reconnaissant explicitement cette dimension, le contextualisme cherche à désamorcer des oppositions apparentes et à clarifier les conditions sous lesquelles un énoncé doit être tenu pour vrai ou pour faux. Enfin, dans leurs versions les plus tempérées, pluralisme et contextualisme ne renoncent pas à l’idée d’une certaine ''unité'' du concept de vérité. Le pluralisme modéré affirme qu’un même concept minimal de vérité se réalise de façons différentes ; le fonctionnalisme alétique soutient que les propriétés diverses de vérité partagent un rôle fonctionnel commun ; le contextualisme maintient que, contexte par contexte, la question de savoir si une proposition est vraie possède encore un sens objectif. ===== Difficultés majeures : inférences mixtes et unité du concept ===== Le pluralisme est toutefois confronté à plusieurs objections sérieuses. L’une des plus discutées est le ''problème des inférences mixtes''. Supposons un raisonnement qui combine une prémisse empirique (vraie par correspondance) et une prémisse mathématique (vraie en vertu de la cohérence ou de la nécessité démonstrative) pour aboutir à une conclusion, par exemple en physique théorique. Comment garantir que la validité logique de l’argument « préserve la vérité » si la vérité n’a pas la même nature pour chacune des prémisses ? Si ce qui rend vraies les prémisses n’est pas unifié, sur quoi repose le fait que la conclusion soit, elle aussi, vraie ? Une autre difficulté est le ''problème de l’unité du concept''. Si la vérité signifie des choses très différentes selon les domaines, ne devons-nous pas admettre qu’il existe plusieurs concepts distincts — plusieurs sens du mot « vrai » — plutôt qu’un concept unique pluriel ? La métaphore du « parapluie conceptuel » (un terme unique couvrant des réalités hétérogènes) ne masque-t-elle pas simplement une homonymie ? On a enfin souligné un ''problème d’engloutissement'' analogue à celui rencontré par le veritisme : si, par exemple, la vérité empirique est conçue comme correspondance, mais que cette correspondance est à son tour évaluée ou justifiée par sa place dans une enquête rationnelle idéale, ne risque-t-on pas de réduire finalement toutes les formes de vérité à une seule notion épistémique centrale (par exemple la superassertibilité) ? Le pluralisme ne tend-il pas, de ce fait, à se replier en un monisme déguisé ? ===== Réponses pluralistes et raffinements contemporains ===== Les pluralistes modérés répondent à ces difficultés en opérant une distinction nette entre le ''concept'' de vérité et les ''propriétés'' qui le réalisent. Il peut y avoir '''un seul concept général''' de vérité — défini minimalement, par exemple, comme ce qui joue le rôle de norme ultime pour la croyance, ou comme ce qui est superassertible — et, simultanément, '''plusieurs propriétés métaphysiquement distinctes''' qui remplissent ce rôle dans différents domaines (correspondance, cohérence, etc.). Dans cette perspective, la logique opère au niveau du concept général de vérité, et non au niveau des propriétés particulières. Les inférences mixtes peuvent alors être considérées comme valides dès lors qu’elles préservent la ''vérité'' au sens conceptuel minimal, même si ce qui rend vraies les prémisses et la conclusion diffère d’un domaine à l’autre. La conséquence logique est une relation entre propositions vraies, sans qu’il soit nécessaire d’unifier ce qui, métaphysiquement, les rend vraies. De plus, le pluralisme contemporain met l’accent sur sa forme modérée plutôt que sur les versions radicales. En conservant un noyau conceptuel unifié, et en admettant que ce noyau peut être réalisé de façon plurielle, il prétend éviter à la fois le relativisme désordonné (où tout critère serait équivalent) et le monisme rigide (qui impose un seul modèle de vérité à tous les domaines). ===== Pluralisme et contextualisme : distinctions et recoupements ===== Pluralisme alétique et contextualisme alétique ne doivent pas être confondus, même s’ils peuvent se combiner. Le pluralisme affirme que la '''nature de la propriété de vérité''' varie d’un domaine à l’autre (physique, mathématique, éthique, etc.) de manière relativement stable. Le contextualisme insiste sur le fait que, à l’intérieur même d’un domaine, les '''conditions de vérité''' d’un énoncé peuvent varier selon des paramètres contextuels (enjeux, présupposés, normes de précision, etc.). Un pluraliste peut très bien être contextualiste : il peut soutenir que différents domaines possèdent des propriétés de vérité différentes et, de surcroît, que, dans chaque domaine, le contexte influe sur la manière dont ces propriétés s’appliquent. Inversement, un contextualiste peut rester moniste : il peut considérer qu’il y a une unique propriété de vérité, tout en maintenant que les conditions de vérité d’un énoncé dépendent fortement du contexte d’énonciation et d’évaluation. ===== Conclusion : l’apport spécifique du pluralisme alétique ===== Pluralisme et contextualisme alétiques invitent à prendre au sérieux la diversité réelle de nos pratiques de vérité. Ils suggèrent qu’il est peut-être illusoire d’espérer une théorie unique et uniforme qui rendrait compte, d’un seul bloc, de ce qui se passe lorsque nous déclarons vrai un résultat expérimental, un théorème mathématique, un jugement moral ou une appréciation esthétique. Sans renoncer nécessairement à l’idée qu’il existe un concept général de vérité, ces approches nous incitent à reconnaître que ce concept peut être réalisé de manières différentes selon les domaines, et que ses conditions d’application sont fréquemment sensibles au contexte. Elles expliquent ainsi pourquoi les grandes théories classiques de la vérité semblent chacune saisir une part légitime du phénomène : chacune a peut-être raison quelque part, dans un certain champ, plutôt que la vérité partout. Reste que le pluralisme, même modéré, doit encore surmonter des difficultés importantes, en particulier la question des inférences mixtes et la préservation d’une unité conceptuelle non purement verbale du terme « vrai ». Mais, qu’on l’adopte ou non, il a eu le mérite de déplacer le débat : au lieu de chercher obstinément ''la'' nature unique de la vérité, il oblige à interroger plus finement ''comment'' la notion de vérité fonctionne effectivement dans nos différentes pratiques discursives et cognitives. À ce titre, il constitue aujourd’hui l’un des axes les plus stimulants de la réflexion contemporaine sur la vérité. === Chapitre 3 : La justification épistémique === ==== 3.1 Nature de la justification ==== ===== Introduction : qu’est-ce qui rend une croyance justifiée ? ===== La justification épistémique est l’une des notions centrales de l’épistémologie contemporaine. Elle pose la question fondamentale : qu’est-ce qui rend une croyance justifiée ou rationnelle ? Autrement dit, qu’est-ce qui distingue une croyance solidement fondée d’une opinion arbitraire, d’un simple préjugé ou d’une superstition ? Dans la tradition issue de Platon, la justification est tenue pour une condition nécessaire de la connaissance : on ne peut véritablement connaître que si l’on dispose de raisons adéquates en faveur de ce que l’on croit. Selon l’analyse classique de la connaissance comme ''croyance vraie justifiée'' (''Justified True Belief'', JTB), dont on trouve déjà les éléments chez Platon, une proposition constitue un cas de connaissance si et seulement si : (1) le sujet y croit, (2) la proposition est vraie, (3) le sujet dispose d’une justification pour cette croyance. Or ce troisième élément demeure obscur : en quoi consiste exactement ce « bon fondement » qui distingue la croyance rationnelle de la croyance téméraire ? C’est autour de cette question que s’articule une grande partie de l’épistémologie contemporaine. ===== Le problème fondamental de la justification ===== La difficulté fondamentale peut être formulée ainsi : qu’est-ce qui confère à une raison, à une preuve ou à un état cognitif le pouvoir de justifier une croyance ? Plus largement : sous quelles conditions une croyance est-elle véritablement justifiée, plutôt que simplement psychologiquement convaincante ou subjectivement persuasive ? Cette interrogation en entraîne immédiatement d’autres. Faut-il tenir pour justificatifs uniquement des éléments de nature propositionnelle (énoncés, jugements), ou bien aussi des états expérientiels (par exemple le vécu perceptif d’« il me semble voir un arbre ») ? La justification doit-elle être accessible au sujet — au sens où celui-ci devrait, par réflexion, pouvoir identifier les raisons qui soutiennent sa croyance ? Une croyance peut-elle être objectivement justifiée si, de fait, le sujet l’adopte pour de mauvaises raisons ? Enfin, comment éviter que l’exigence de justification ne conduise à une régression à l’infini ? Le problème de la régression est en effet la difficulté classique de toute théorie de la justification. Pour que la croyance que ''P'' soit justifiée, elle semble devoir être soutenue par une autre croyance que ''Q''. Mais, pour que ''Q'' soit à son tour justifiée, elle doit reposer sur une autre croyance que ''R'', et ainsi de suite. On obtient alors soit une régression infinie, apparemment insoutenable pour un esprit fini ; soit un cercle de justifications mutuelles, généralement jugé vicié d’un point de vue épistémique ; soit l’arrêt arbitraire du processus sur une croyance qui ne serait plus elle-même justifiée. L’un des grands enjeux des théories de la justification est précisément de proposer une issue à cette aporie. ===== Internalisme et externalisme : le grand clivage ===== Les débats contemporains se structurent en grande partie autour de l’opposition entre internalisme et externalisme épistémiques. L’''internalisme épistémique'' soutient que la justification d’une croyance est entièrement déterminée par des facteurs internes au sujet, c’est-à-dire par des états mentaux auxquels il peut, au moins en principe, avoir accès par réflexion. Pour qu’une croyance soit justifiée, il ne suffit pas qu’elle ait été produite de la « bonne » manière : il faut encore que le sujet puisse, en examinant ses propres états cognitifs, reconnaître les raisons qui la soutiennent. La justification est alors conçue comme quelque chose de transparent ou de « visible » pour la conscience réflexive. L’''externalisme épistémique'', à l’inverse, affirme que la justification d’une croyance peut dépendre de facteurs externes au champ de conscience du sujet. Ce qui fait qu’une croyance est justifiée peut relever de caractéristiques objectives de son mode de formation (par exemple la fiabilité du processus cognitif en cause), sans que le sujet ait à en être conscient ni même capable de s’en rendre compte. Ce qui importe, pour l’externaliste, n’est pas tant ce dont le sujet a conscience que la manière dont la croyance est effectivement reliée au monde par un processus approprié. Cette opposition recoupe un désaccord plus profond sur la fonction de la justification. Pour l’internaliste, la justification est étroitement liée à l’évaluation réflexive de nos croyances : elle doit pouvoir être invoquée dans un contexte de discussion, de doute ou de délibération. Pour l’externaliste, elle renvoie plutôt à la fiabilité objective de nos pratiques cognitives : ce qui compte, c’est que nos croyances soient produites par des mécanismes qui, de fait, conduisent le plus souvent à la vérité. ===== Le fondationnalisme : la structure de base de la justification ===== Le ''fondationnalisme'' est une théorie de la structure de la justification. Il soutient que l’édifice de nos croyances justifiées possède une architecture hiérarchique. Certaines croyances sont de base : elles sont justifiées de manière non inférentielle, c’est-à-dire qu’elles ne tirent pas leur justification d’autres croyances. D’autres croyances, dites non basiques, sont justifiées de manière dérivée, en vertu de leur relation (logique, inductive, explicative) aux croyances de base. L’idée centrale est que la régression de la justification doit s’arrêter quelque part. Les croyances de base constituent ce point d’arrêt : elles ne sont pas justifiées par d’autres croyances, mais disposent d’une forme d’évidence immédiate (perceptive, introspective, logique, parfois mémorielle) qui suffit à les rendre prima facie rationnelles. Les croyances non basiques héritent alors leur justification de ces fondements, par inférence ou par soutien explicatif. Les fondationnalistes divergent cependant sur la nature exacte de ces croyances de base. Le fondationnalisme classique tend à exiger une forme forte de sécurité : les croyances de base seraient infaillibles ou du moins indubitables (par exemple certains jugements immédiats de conscience ou certaines vérités logico-mathématiques évidentes). Le fondationnalisme modéré renonce à cette infaillibilité : les croyances de base peuvent, en principe, être erronées, mais elles bénéficient d’une justification immédiate suffisamment robuste pour jouer le rôle de fondation. Enfin, un fondationnalisme externaliste fait dépendre le caractère « basique » non d’une évidence intrinsèque pour le sujet, mais du fait que la croyance provient d’un processus fiable : une perception normale en conditions ordinaires produirait ainsi des croyances de base justifiées, même si le sujet n’a pas réfléchi aux raisons de leur fiabilité. ===== Le cohérentisme : une approche holistique ===== Le ''cohérentisme'' propose une alternative radicale au fondationnalisme. Il refuse l’idée même de croyances privilégiées qui serviraient de fondement ultime. Selon le cohérentisme, une croyance est justifiée dans la mesure où elle s’insère de manière cohérente dans l’ensemble global des croyances du sujet. Ce n’est pas la relation à un socle de croyances auto-évidentes qui confère la justification, mais l’appartenance à un système suffisamment intégré, harmonieux et explicativement puissant. La justification apparaît alors comme holistique : une croyance isolée ne peut être évaluée qu’en fonction de la place qu’elle occupe au sein du réseau de croyances du sujet. Une croyance qui renforce la cohérence globale du système, qui améliore sa puissance explicative ou qui permet de résoudre des tensions internes aura, de ce point de vue, un meilleur statut justificatif qu’une croyance qui introduit dissonances et contradictions. Le cohérentisme présente des atouts réels. Il rend compte du fait que même nos croyances apparemment les plus « basiques » (perceptives, par exemple) peuvent être révisées à la lumière d’autres informations ; il explique aussi pourquoi la justification n’est jamais purement locale mais dépend toujours de l’ajustement d’ensemble. Toutefois, cette approche rencontre des difficultés sérieuses. On peut imaginer, au moins en pensée, un système de croyances parfaitement cohérent et pourtant massivement faux : pourquoi un tel système serait-il justifié ? De plus, le cohérentisme doit expliquer comment ce réseau de croyances reste connecté à la réalité, et ne devient pas un simple château de cartes conceptuel flottant au-dessus du monde. ===== Le fiabilisme : la justification par la fiabilité des processus ===== Le ''fiabilisme'' (''reliabilism'') est une forme d’externalisme qui définit la justification en termes de fiabilité des processus de formation des croyances. Selon cette approche, une croyance est justifiée si et seulement si elle est produite par un processus cognitif généralement fiable, c’est-à-dire un processus qui, dans une proportion suffisante de cas, conduit à des croyances vraies. Ainsi, les croyances issues d’une perception normale dans des conditions ordinaires, celles qui proviennent d’une mémoire non pathologique, ou encore celles qui résultent de raisonnements logiques corrects, seront typiquement tenues pour justifiées parce que les processus qui les produisent sont, dans notre environnement, globalement fiables. À l’inverse, les croyances formées par astrologie ou par tirage au sort ne seront pas justifiées, même si elles se révèlent par hasard vraies, car les processus qui y conduisent sont globalement non fiables. Le fiabilisme présente l’avantage de relier étroitement justification et vérité : justifier une croyance, c’est la raccorder à des mécanismes qui, empiriquement, nous conduisent le plus souvent à des croyances vraies. Il évite ainsi de faire de la justification une pure affaire de conscience subjective. Mais cette théorie n’est pas exempte de difficultés. Le fameux scénario du « mauvais démon » (ou du cerveau dans une cuve) suggère que deux sujets psychologiquement indiscernables, dont l’un vit dans un monde normal et l’autre dans un monde systématiquement trompeur, devraient, intuitivement, être également justifiés ; or le fiabilisme standard semble obligé de dire que le second ne l’est pas, puisque les processus qui le guident sont en réalité non fiables. D’autre part, l’externalisme fiabiliste soulève la question de l’accessibilité : si la justification dépend de la fiabilité objective de processus que le sujet ne connaît pas, en quel sens peut-il encore savoir que ses croyances sont justifiées ? ===== L’évidentialisme : la justification par l’évidence ===== On désigne par ''évidentialisme'' (''evidentialism'') la thèse selon laquelle la justification d’une croyance dépend uniquement de l’évidence dont dispose le sujet. Une croyance est justifiée si, et seulement si, elle est appropriée à la lumière de l’ensemble des données, raisons ou indices dont le sujet dispose effectivement. La justification est alors envisagée comme un rapport d’ajustement ou de conformité entre ce que le sujet croit et ce que son évidence totale rend rationnel de croire. L’évidentialisme est généralement couplé à un internalisme : l’évidence pertinente est constituée par les états mentaux du sujet (perceptions, souvenirs, intuitions, autres croyances) auxquels il peut, en principe, avoir accès par réflexion. L’évidentialiste défendra, par exemple, qu’il est irrationnel de persister à croire ''P'' si l’on reconnaît que la quasi-totalité de l’évidence dont on dispose va à l’encontre de ''P''. À l’inverse, lorsque toute l’évidence disponible converge en faveur de ''P'', la croyance que ''P'' est, prima facie, justifiée. ===== Justification propositionnelle et justification doxastique ===== Les discussions contemporaines introduisent une distinction devenue classique entre justification ''propositionnelle'' et justification ''doxastique''. * On dit qu’un sujet dispose d’une '''justification propositionnelle''' pour ''P'' lorsqu’il possède de bonnes raisons ou de bonnes preuves en faveur de ''P'', indépendamment du fait qu’il croie effectivement ''P'' ou qu’il fonde sa croyance sur ces raisons. Il pourrait, en principe, s’appuyer sur ces raisons pour croire ''P'' de manière rationnelle. * On dit qu’un sujet a une '''justification doxastique''' pour sa croyance que ''P'' lorsqu’il croit effectivement ''P'' en se fondant sur les raisons appropriées dont il dispose. La justification doxastique requiert donc non seulement la possession de bonnes raisons, mais le fait de baser réellement sa croyance sur ces raisons. Cette distinction permet de clarifier de nombreux cas. Un sujet peut, en principe, avoir toute l’évidence requise pour justifier ''P'', mais, pour des raisons psychologiques contingentes, croire ''P'' sur la base d’un préjugé ou d’un motif inapproprié. Sa croyance ne sera alors pas doxastiquement justifiée, même si des raisons suffisantes existaient à sa disposition. ===== Le problème de Gettier et la justification ===== Les célèbres contre-exemples d’Edmund Gettier (1963) ont montré que la définition classique de la connaissance comme ''croyance vraie justifiée'' n’est pas suffisante. Il existe des situations où un sujet possède une croyance vraie, pour laquelle il dispose de bonnes raisons, mais où l’on hésite à parler de connaissance parce que la vérité de la croyance résulte en partie du hasard ou d’une coïncidence fortuite. Ces cas ont conduit les épistémologues à examiner de plus près la structure de la justification. Il ne suffit pas que la croyance soit accompagnée d’arguments persuasifs ; il faut encore que la manière dont ces raisons conduisent à la croyance exclue certaines formes de chance épistémique. Les approches externalistes, en particulier, ont vu dans les cas de Gettier un argument pour renforcer la dimension causale ou fiable de la justification : une croyance ne peut constituer une connaissance que si elle est reliée de manière adéquate, non seulement rationnelle mais aussi causale, au fait qui la rend vraie. ===== Conclusion : un concept central et toujours discuté ===== Après des décennies de débats, la notion de justification épistémique demeure l’une des plus disputées de la philosophie contemporaine. Le fondationnalisme insiste sur la nécessité de croyances de base non inférentielles ; le cohérentisme met l’accent sur la cohérence globale de nos systèmes de croyances ; le fiabilisme souligne l’importance de la fiabilité objective de nos processus cognitifs ; l’évidentialisme rappelle que la justification est, pour une large part, affaire d’évidence disponible et d’ajustement rationnel à cette évidence. Chacune de ces approches met en lumière une dimension authentique de notre pratique épistémique, sans parvenir pour autant à s’imposer comme solution définitive. De nombreux auteurs contemporains s’orientent vers des positions hybrides ou pluralistes, admettant que différents types de croyances (perceptuelles, mémorielles, mathématiques, morales, testimoniales) peuvent être justifiés selon des modalités partiellement distinctes, et que la justification réelle combine souvent des éléments internes (évidence, accessibilité réflexive) et externes (fiabilité, lien causal adéquat au réel). Quoi qu’il en soit, la tentative de clarifier ce qui rend une croyance véritablement justifiée reste au cœur du projet épistémologique : elle conditionne notre compréhension de la connaissance, mais aussi de la rationalité, de l’enquête scientifique et, plus largement, de ce que signifie pour nous croire de manière responsable. ==== 3.2 Internalisme versus externalisme ==== ===== Introduction : un clivage majeur au cœur de l'épistémologie ===== Le débat entre ''internalisme'' et ''externalisme'' constitue l’un des clivages majeurs de l’épistémologie contemporaine. Il porte sur une question fondamentale : les facteurs qui déterminent si une croyance est justifiée sont-ils entièrement internes au sujet, ou peuvent-ils inclure des facteurs externes ? Autrement dit, la justification épistémique dépend-elle uniquement des états mentaux du sujet et de ce à quoi il a un accès réflexif, ou peut-elle aussi dépendre de faits extérieurs à la conscience du sujet, comme la structure causale de son environnement ou la fiabilité objective de ses processus cognitifs ? Ce débat s’est cristallisé dans le sillage du problème de Gettier, à partir des années 1960. La mise en évidence de cas où un sujet possède une croyance vraie et justifiée qui ne semble pourtant pas constituer une véritable connaissance a conduit les épistémologues à réexaminer la relation entre justification et connaissance. Les tentatives de « réparer » la définition classique de la connaissance comme croyance vraie justifiée ont alors donné naissance à deux grandes familles de réponses : celles qui insistent sur ce qui est accessible ''de l’intérieur'' au sujet, et celles qui insistent sur les relations ''externes'' entre le sujet, ses croyances et le monde. ===== L’internalisme épistémique : la centralité de l’accès ===== L’internalisme soutient que la justification d’une croyance est entièrement déterminée par des facteurs internes au sujet, en un sens qu’il convient de préciser. De façon générale, l’internaliste estime que, pour qu’une croyance soit véritablement justifiée, le sujet doit, au moins en principe, pouvoir savoir en vertu de quoi elle l’est. La justification doit ainsi dépendre d’éléments enracinés dans la vie mentale du sujet : expériences, états doxastiques, souvenirs, capacités de raisonnement, et non de simples faits objectifs qui resteraient à jamais hors de portée de sa réflexion. On résume parfois cette position en disant que la justification « supervient sur l’interne ». Cette formule signifie que si deux sujets sont exactement identiques du point de vue de leurs états mentaux – mêmes expériences, mêmes croyances, mêmes dispositions réflexives –, alors ils doivent avoir le même statut justificatoire, quels que soient par ailleurs les faits du monde extérieur. Si l’on modifie l’environnement sans modifier les états mentaux, on ne doit pas, du point de vue internaliste, modifier le degré de justification. Les internalistes se divisent eux-mêmes selon la manière dont ils définissent ce qui compte comme ''interne''. Une première approche, souvent qualifiée d’''internalisme d’accès'' (''accessibilisme''), soutient que les facteurs qui déterminent la justification doivent être accessibles au sujet par la réflexion : le sujet doit pouvoir, en examinant son propre esprit, prendre conscience des raisons, preuves ou arguments qui soutiennent sa croyance. Il n’est pas nécessaire qu’il y pense effectivement en permanence, mais il doit être en position de les « faire remonter » à la conscience par un effort réflexif. Une seconde approche, parfois désignée comme ''mentalisme'', élargit ce qui peut compter comme interne : sont internes tous les états authentiquement mentaux du sujet, y compris ceux auxquels il n’a pas un accès réflexif immédiat. Dans cette perspective, certains états non thématisés, voire préconscients, peuvent contribuer à la justification, pourvu qu’ils appartiennent réellement à la vie mentale du sujet. Dans la tradition internaliste classique, l’accent est principalement mis sur l’accessibilité. L’intuition directrice est qu’on ne peut être tenu pour ''épistémiquement responsable'' d’une croyance – c’est-à-dire loué ou blâmé pour l’avoir adoptée – que si l’on est en mesure de ‘‘voir’’ les raisons qui la soutiennent. Si les facteurs qui rendent ma croyance justifiée m’étaient à jamais inaccessibles, il semblerait étrange de dire que j’agis de manière rationnelle en la conservant ou en la révisant. L’internalisme cherche ainsi à articuler la justification avec des notions comme la responsabilité, la transparence réflexive et le contrôle rationnel que le sujet exerce sur ses états doxastiques. Certains internalistes, plus exigeants, défendent une forme « forte » d’accessibilisme : pour qu’une croyance soit justifiée, il faudrait que le sujet soit effectivement conscient, hic et nunc, des raisons qui la soutiennent. D’autres, plus modérés, considèrent qu’il suffit que le sujet soit en position de les rendre présentes à sa conscience par un effort de réflexion. Cette seconde variante, moins rigide, est la plus largement défendue, car elle permet de tenir compte du fait que nous ne réfléchissons pas en permanence à toutes nos justifications, tout en maintenant le lien étroit entre justification et possibilité de prise de conscience. ===== L’externalisme épistémique : au-delà de l’esprit ===== L’externalisme adopte une stratégie presque inverse. Selon cette famille de théories, la justification d’une croyance peut dépendre de facteurs externes au sujet, c’est-à-dire de faits qui ne sont pas nécessairement accessibles à sa conscience et qui ne superviennent pas sur ses seuls états mentaux. Ce qui rend une croyance justifiée peut alors être, par exemple, la fiabilité objective du processus par lequel elle a été formée, la relation causale adéquate entre la croyance et son objet, ou encore le bon fonctionnement des facultés cognitives du sujet dans un environnement approprié. Dans cette perspective, il est possible que deux sujets mentalement indiscernables – ayant exactement les mêmes sensations, les mêmes croyances conscientes et les mêmes raisonnements – aient des statuts justificatoires différents, si leurs environnements diffèrent de manière épistémiquement pertinente. La justification ne dépend plus seulement de ce que le sujet ''vit de l’intérieur'', mais aussi de la manière dont ses croyances sont reliées au monde dans lequel il se trouve réellement. Le célèbre cas de pensée du « démon trompeur » permet d’illustrer ce désaccord. Imaginons deux sujets, que l’on appellera Pat et Nat, qui ont, à chaque instant, des états mentaux strictement identiques. Pat vit dans un monde ordinaire, peuplé d’arbres, de tables et de montagnes : ses expériences visuelles sont causées par des objets concrets. Nat, en revanche, est victime d’un démon cartésien tout-puissant qui produit en lui exactement les mêmes expériences, sans qu’il y ait derrière celles-ci un monde extérieur correspondant. Du point de vue d’un internaliste, Pat et Nat étant mentalement indiscernables, leurs croyances perceptives ont le même statut justificatoire. Du point de vue d’un externaliste fiabiliste, au contraire, les croyances de Pat sont justifiées parce qu’elles sont issues d’un processus perceptif fiable dans un environnement normal, alors que celles de Nat ne le sont pas, car elles sont systématiquement produites par un dispositif trompeur qui ne met pas le sujet en contact adéquat avec le réel. Les différentes versions de l’externalisme se distinguent en fonction du type précis de facteur externe qu’elles mettent au centre. Le ''fiabilisme'' insiste sur la fiabilité des processus de formation des croyances : une croyance est justifiée si elle provient d’un processus qui, dans une large gamme de situations proches, tend à produire des croyances vraies plutôt que fausses. D’autres auteurs défendent des ''théories du suivi'' (''tracking theories'') : une croyance est adéquatement justifiée si le sujet croirait différemment si le monde était différent, de sorte que sa croyance « suit » la vérité à travers les mondes possibles pertinents. Les ''théories de la sécurité'' (''safety views'') mettent plutôt l’accent sur l’idée qu’une croyance justifiée ne doit pas « facilement » être fausse : dans les circonstances proches de celles où le sujet se trouve, il ne doit pas être facile qu’il forme la même croyance en situation de fausseté. Enfin, le ''fonctionnalisme adéquat'' (inspiré des travaux d’Alvin Plantinga) considère qu’une croyance est justifiée si elle résulte des facultés cognitives du sujet fonctionnant correctement, conformément au dessein ou à la fonction pour laquelle elles ont été « conçues », dans un environnement pour lequel elles sont adaptées. Toutes ces approches ont en commun de refuser de réduire la justification à ce qui est directement introspectible. Pour l’externaliste, ce qui importe avant tout, du point de vue de la valeur épistémique, est que les croyances soient effectivement bien connectées à la vérité, même si le sujet n’est pas toujours en mesure de se rendre compte de cette connexion. ===== Les motivations principales du débat ===== Les partisans de l’internalisme et de l’externalisme ne se distinguent pas seulement par leurs définitions techniques, mais aussi par les intuitions philosophiques qui motivent leurs positions. Du côté internaliste, une première motivation majeure tient à la notion de responsabilité épistémique. Nous louons ou blâmons les agents, nous leur demandons des comptes pour leurs croyances : nous leur reprochons d’être crédules, dogmatiques, ou au contraire nous les félicitons pour leur prudence et leur esprit critique. Cette pratique semble présupposer que les sujets ont accès aux raisons de croire qu’ils invoquent, sans quoi il serait difficile de les considérer comme véritablement responsables. Une deuxième motivation est liée aux préoccupations sceptiques. Si la justification dépend, pour une grande part, de facteurs externes qui nous échappent, il devient délicat de savoir si nous sommes effectivement justifiés, ce qui paraît renforcer le scepticisme. L’internalisme cherche à préserver l’idée d’un certain contrôle réflexif que le sujet exerce sur la légitimité de ses croyances. Enfin, les internalistes invoquent souvent l’évidence fournie par l’introspection : lorsque nous examinons nos croyances, c’est en scrutant nos expériences, nos inférences, nos souvenirs, et non en inspectant des faits externes dont nous ne savons parfois presque rien. Les externalistes sont animés par d’autres préoccupations. Ils insistent d’abord sur la nécessité de maintenir un lien étroit entre justification et vérité. Une théorie de la justification qui n’intègre pas des conditions objectives – comme la fiabilité des processus cognitifs ou la sécurité des croyances – risque de se détacher de ce qui fait la valeur première de la croyance : être vraie. Les externalistes soulignent aussi que de nombreux sujets – enfants en bas âge, animaux, ou adultes peu portés à la réflexion – semblent néanmoins détenir des croyances que nous jugeons ''épistémiquement'' bonnes, même s’ils sont incapables d’articuler des raisons ou de satisfaire aux exigences internalistes. Enfin, pour beaucoup d’externalistes, il est simplement contre-intuitif d’affirmer que Nat, le sujet systématiquement trompé par un démon, est tout aussi justifié que Pat : il nous semble naturel de dire que Nat n’a pas vraiment un bon contact cognitif avec le monde, même si, de l’intérieur, ses expériences ressemblent parfaitement à celles d’un sujet bien informé. ===== Les défis majeurs pour chaque position ===== Chaque camp affronte des difficultés sérieuses que ses adversaires ne manquent pas de souligner. Les internalistes doivent d’abord répondre au défi du « monde du démon ». S’ils admettent que Nat, dans un monde entièrement illusoire, est tout aussi justifié que Pat, ils doivent expliquer pourquoi nous devrions accorder la même valeur épistémique à des croyances qui, dans un cas, sont systématiquement vraies, et dans l’autre, presque toujours fausses. Ils sont également confrontés à une difficulté conceptuelle : la notion même d’« accès » paraît déjà chargée d’un contenu épistémique – avoir accès, n’est-ce pas, en un certain sens, ''savoir'' ? Le risque est alors de définir la justification en termes d’une autre notion qui lui est étroitement apparentée, au lieu d’en donner une véritable analyse. Enfin, l’internalisme semble avoir du mal à rendre compte de croyances que nous jugeons spontanément justifiées sans qu’un travail réflexif conscient soit requis, par exemple les croyances ordinaires de perception chez les enfants ou chez les adultes qui ne se livrent pas à une introspection sophistiquée. Les externalistes, de leur côté, doivent affronter le reproche d’« inaccessibilité ». Si la justification dépend de facteurs externes qui échappent au sujet, celui-ci risque de ne jamais pouvoir savoir s’il est effectivement justifié. Or il semble faire partie de notre pratique ordinaire que nous puissions, au moins dans une certaine mesure, évaluer nos propres états épistémiques. Les fiabilistes se heurtent, en outre, à ce que l’on appelle le « problème de la généralité » : pour évaluer la fiabilité d’un processus de formation de croyances, encore faut-il déterminer de quel processus il s’agit exactement. Doit-on parler du « système visuel humain », de la « perception en plein jour chez un sujet sans déficience », ou d’un sous-processus encore plus spécifique ? Selon la manière dont on délimite le processus, son taux de fiabilité peut varier, ce qui rend la théorie indéterminée si l’on ne précise pas un critère non arbitraire. Enfin, les externalistes doivent expliquer comment concilier leur thèse avec l’intuition selon laquelle Nat, bien que selon eux non justifié, ne mérite aucun blâme pour ses croyances : il fait, de son point de vue, tout ce qu’un agent rationnel peut faire. Il y a là une tension entre la dimension « axiologique » de la justification (valeur épistémique d’une croyance) et sa dimension « normative » (ce qu’il est raisonnable d’exiger d’un agent). ===== Les positions intermédiaires et synthétiques ===== Face à ces difficultés réciproques, de nombreux épistémologues ont cherché des voies médianes. Certains défendent un ''internalisme modéré'' : ils maintiennent que la justification dépend en premier lieu de facteurs internes, dont le sujet peut rendre compte, mais admettent que des conditions externes – comme le bon fonctionnement des facultés ou la conformité à des normes objectives – jouent un rôle complémentaire. Dans cette perspective, l’internalisme fournirait les conditions de ''responsabilité'' du sujet, tandis que certaines exigences externalistes garantiraient la bonne connexion à la vérité. Inversement, certains externalistes adoptent des formes ''nuancées'' de leur position. Ils reconnaissent, par exemple, que pour qu’une croyance soit pleinement justifiée, il ne suffit pas qu’elle résulte d’un processus fiable : encore faut-il que le sujet soit disposé à réagir de manière appropriée à des contre-preuves, qu’il ne soit pas indifférent à l’évidence disponible, et qu’il entretienne un certain rapport réflexif à ses propres croyances. L’externalisme n’exclut alors pas la prise en compte d’exigences internes, mais refuse de les considérer comme suffisantes ou exclusives. Une autre orientation consiste à adopter un ''pluralisme justificatif''. Plutôt que de chercher une conception unique de la justification valable pour tous les usages du terme, certains auteurs soutiennent qu’il existe plusieurs notions apparentées de justification, adaptées à des objectifs épistémiques distincts. Pour attribuer une responsabilité ou évaluer la ''démarche'' d’un agent, une conception internaliste, centrée sur l’accès aux raisons, serait la plus pertinente. Pour expliquer la connaissance en tant que relation réussie au vrai, une conception plus externaliste, orientée vers la fiabilité ou la sécurité des croyances, serait mieux adaptée. Le débat ne porterait plus alors sur la question de savoir qui a ''absolument'' raison, mais sur la clarification des différents rôles que le concept de justification joue dans nos pratiques théoriques et ordinaires. ===== Les implications pratiques du débat ===== Ce débat n’est pas seulement d’intérêt théorique ; il a des conséquences pour d’autres domaines de la philosophie et pour notre manière d’évaluer croyances et pratiques cognitives. Pour la théorie de la connaissance, la question est de savoir si la connaissance exige que le sujet ait un certain accès réflexif à ses raisons. Un internaliste aura tendance à exiger, pour parler de connaissance, que le sujet soit en mesure d’expliquer en vertu de quoi il croit, au moins dans les cas paradigmatiques. Un externaliste peut être plus enclin à admettre des cas de connaissance « implicite », où le sujet est correctement relié au monde sans pouvoir formuler les raisons qui rendent sa croyance justifiée. Ces divergences influencent la manière dont on traite les cas marginaux : connaissances animales, intuitions perceptives immédiates, connaissances tacites, etc. En épistémologie appliquée – par exemple dans l’évaluation du témoignage, des médias d’information ou de l’expertise scientifique –, les divergences jouent également un rôle. Une approche internaliste insistera sur la nécessité pour les citoyens d’examiner les sources, de comprendre les arguments, de vérifier les conditions dans lesquelles une information a été obtenue. Une approche plus externaliste accordera davantage de poids au fonctionnement global des institutions cognitives (universités, revues scientifiques, agences d’expertise), à leur fiabilité statistique, même si les individus ne peuvent pas toujours, à titre personnel, accéder aux détails justificatifs. La manière dont on articule ces deux dimensions – contrôle réflexif des sujets d’un côté, fiabilité des structures cognitives de l’autre – conditionne notre conception d’une société épistémiquement saine. ===== Conclusion : un débat durablement structurant ===== Après plusieurs décennies de discussions, aucun consensus ne s’est imposé en faveur de l’internalisme ou de l’externalisme. Chaque position met en lumière des aspects essentiels de notre vie cognitive. Les internalistes rappellent que la justification n’est pas un simple fait objectif relatif à nos croyances, mais aussi une norme à laquelle nous essayons, en tant qu’agents rationnels, de nous conformer en examinant nos raisons. Les externalistes insistent, pour leur part, sur la nécessité de ne pas détacher la valeur épistémique de la croyance de sa connexion effective à la vérité, connexion qui peut dépendre de faits que nous ne maîtrisons pas intérieurement. Il est possible que la question « la justification est-elle fondamentalement interne ou externe ? » soit, en elle-même, trop grossièrement posée. Une approche plus fine consisterait à distinguer les diverses fonctions que le concept de justification remplit – évaluer des agents, expliquer la connaissance, guider la recherche de l’information fiable – et à reconnaître que ces fonctions ne requièrent pas nécessairement les mêmes conditions. Dans cette perspective, le débat entre internalisme et externalisme ne disparaît pas, mais se transforme en un travail de clarification conceptuelle plus différencié. Quoi qu’il en soit, la controverse demeure l’une des plus actives de l’épistémologie contemporaine. Elle continue de susciter des positions intermédiaires, des synthèses originales et des reformulations qui, loin de l’épuiser, montrent au contraire combien la question de savoir ce qui rend nos croyances véritablement justifiées est centrale pour toute réflexion sur la connaissance. ==== 3.3 Structure de la justification : fondationnalisme ==== ===== Introduction : le recours aux croyances de base ===== Le fondationnalisme constitue l’une des théories les plus anciennes et les plus influentes concernant la ''structure'' de la justification épistémique. Son idée directrice peut se formuler ainsi : les croyances justifiées ne forment pas un ensemble informe, mais un système organisé de manière hiérarchique, dont la base est constituée par des croyances de base, c’est-à-dire des croyances qui ne dépendent d’aucune autre croyance pour être justifiées, et qui soutiennent l’édifice entier des croyances dérivées. Le fondationnalisme prétend ainsi résoudre le problème de la régression infinie des raisons en affirmant que cette régression trouve un terme naturel dans des croyances fondamentales, qui fournissent un point d’arrêt légitime et justifié. Alors que l’internalisme et l’externalisme portent principalement sur les ''facteurs'' qui déterminent la justification (internes au sujet ou externes à lui), le fondationnalisme s’intéresse à la ''forme'' d’ensemble de notre système de croyances : la manière dont les croyances justifiées s’ordonnent et s’articulent les unes aux autres au sein d’une architecture globale. Deux questions commandent toute version du fondationnalisme. Premièrement : qu’est-ce qui confère à une croyance le statut de croyance ''de base'', c’est-à-dire de croyance justifiée indépendamment de toute autre croyance ? Deuxièmement : comment les croyances qui ne sont pas de base reçoivent-elles leur justification d’une manière qui s’enracine ultimement dans ces fondations ? ===== Le fondationnalisme : architecture conceptuelle ===== '''La structure hiérarchique des croyances justifiées''' Le fondationnalisme repose sur deux thèses étroitement liées : * '''Thèse des croyances de base''' : il existe au moins certaines croyances qui bénéficient d’une justification ''non inférentielle'', indépendante de tout soutien fourni par d’autres croyances. Ces croyances de base possèdent une suffisance justificatrice qui leur est propre. * '''Thèse de la chaîne justificatrice''' : toute croyance qui n’est pas de base – une croyance ''non de base'' – doit recevoir sa justification par l’intermédiaire d’une ''chaîne justificatrice'' descendante, qui s’appuie, directement ou indirectement, sur des croyances de base. Aucune croyance dérivée ne peut être justifiée uniquement par d’autres croyances elles-mêmes dérivées, sans que la chaîne ne se termine, sous peine de régression infinie ou de circularité. Le fondationnaliste se représente ainsi la justification sous la forme d’une structure pyramidale : à la base, des croyances fondatrices dotées d’une justification autonome ; plus haut, des croyances non de base, dont la justification se déploie par des relations inférentielles qui renvoient, en dernière analyse, vers ces fondations stables. C’est cette organisation hiérarchisée qui est censée conférer au système de croyances sa solidité épistémique globale. '''La justification des croyances de base''' Une difficulté majeure surgit aussitôt : si les croyances de base ne tirent pas leur justification d’autres croyances, d’où provient cette justification ? Différentes variantes du fondationnalisme proposent des réponses distinctes. * Selon certaines versions, les croyances de base possèdent une forme d’''auto-justification'' : elles seraient justifiées en vertu de leurs seules propriétés intrinsèques (par exemple leur évidence irrésistible), sans appel à un facteur extérieur. Cette solution a une certaine élégance conceptuelle, mais elle est métaphysiquement exigeante : comment comprendre qu’une croyance « se justifie » elle-même sans circularité ? * D’autres fondationnalistes soutiennent que les croyances de base reçoivent leur justification de ''sources non doxastiques'', au premier rang desquelles l’expérience perceptive immédiate (ce qui apparaît dans le champ visuel, auditif, tactile) et l’expérience introspective (la conscience directe de ses propres états mentaux, comme la douleur ou la tristesse). La justification est alors ancrée dans l’expérience vécue, qui jouerait le rôle de « donné » soutenant certaines croyances. * Enfin, des fondationnalistes de sensibilité externaliste considèrent que les croyances de base sont justifiées du fait qu’elles proviennent de processus de formation des croyances objectivement fiables : les sens, la mémoire normale, certaines formes de raisonnement, dès lors qu’ils fonctionnent correctement dans un environnement approprié. La justification n’est plus liée à un caractère d’évidence interne, mais à la qualité causale des mécanismes cognitifs qui engendrent la croyance. ===== Le problème de la régression infinie : l’argument fondationnaliste classique ===== '''L’argument de la régression''' L’argument de la régression (souvent désigné par l’expression anglaise ''regress argument'') est la principale motivation du fondationnalisme. Il se déploie en plusieurs étapes. Considérons une croyance P qui est, supposons-le, justifiée. Si la justification de P est d’ordre inférentiel, elle provient d’une autre croyance Q. Mais, pour que Q puisse justifier P, Q doit elle-même être justifiée. On invoquera alors une croyance R pour justifier Q, et ainsi de suite. Dès lors, quatre possibilités logiquement exhaustives se présentent : * '''Régression infinie''' : la chaîne justificatrice s’étend à l’infini, sans jamais atteindre un point d’arrêt. Or, il paraît psychologiquement impossible qu’un sujet humain possède effectivement une infinité de croyances conscientes formant une telle chaîne. Même en faisant abstraction de cette impossibilité psychologique, la justification semble toujours « fuyante » : pour chaque croyance, on peut toujours demander une nouvelle raison, sans jamais atteindre une justification complète. * '''Circularité''' : la chaîne, au lieu de se prolonger à l’infini, revient à son point de départ. Une croyance B est justifiée par C, C par D, et D, finalement, par B. Cette circularité est généralement jugée épistémiquement vicieuse : le soutien mutuel de croyances se renvoyant les unes aux autres ne fait que refléter un enfermement dans un même cercle, sans fournir de véritable ancrage dans la réalité. * '''Arrêt dans l’injustifié''' : la chaîne s’interrompt sur des croyances qui, elles, ne sont pas justifiées. On pose alors comme « données » de simples opinions dépourvues de fondement, pour en justifier d’autres. Mais il est difficilement acceptable qu’une croyance injustifiée serve de base légitime à la justification d’une autre : si la source est épistémiquement défectueuse, tout ce qui en dérive le sera également. * '''Arrêt dans des croyances de base justifiées''' : la chaîne aboutit à des croyances qui possèdent une justification non dérivée, indépendante de tout soutien doxastique préalable. Ces croyances « de base » sont justifiées, mais ne sont pas justifiées ''par'' d’autres croyances. Pour le fondationnaliste, les trois premières possibilités sont inacceptables : la régression infinie rend la justification inatteignable, la circularité ne fournit qu’une apparence de soutien, et l’arrêt dans l’injustifié nie le principe même de suffisance des raisons. Il en conclut qu’il ''doit'' exister des croyances de base justifiées, si l’on veut sauver l’idée même d’une justification rationnelle. ===== Variantes du fondationnalisme et traits distinctifs ===== '''Fondationnalisme classique : infaillibilité et certitude''' Le fondationnalisme classique – que l’on peut qualifier de ''fort'' – impose les exigences les plus strictes quant à la nature des croyances de base. Il soutient que celles-ci doivent être ''infaillibles'' ou au moins ''incorrigibles'' : elles ne peuvent pas être fausses, ou du moins il n’est jamais rationnel d’en douter. Par ailleurs, cette version tend à considérer que les croyances non de base ne peuvent être justifiées que par des inférences ''déductives'', seules garanties de transférer intégralement la vérité et la justification des prémisses vers la conclusion. L’histoire de la philosophie offre divers candidats à ce statut fondationnel fort : * des énoncés d’auto-référence immédiate, tels que « Je pense » ou « Il m’apparaît maintenant du rouge », dont la négation semble auto-contradictoire dans le contexte où ils sont énoncés ; * des descriptions très fines de l’expérience interne (« J’éprouve maintenant une vive douleur »), que l’on suppose soustraites au doute ; * certains principes logiques élémentaires, comme le principe de non-contradiction, appréhendés comme immédiatement évidents. Cette version classique a pour elle le prestige de la certitude, mais elle se heurte à plusieurs difficultés. D’une part, les croyances réellement infaillibles semblent rarissimes ; d’autre part, l’idée que seule la déduction puisse transmettre la justification paraît en décalage profond avec la pratique scientifique et ordinaire, largement fondée sur des inférences non déductives (induction, abduction). '''Fondationnalisme modéré : faillibilité et pluralisme inférentiel''' Le fondationnalisme modéré – ou ''faible'' – renonce à l’idéal d’infaillibilité. Il affirme que les croyances de base peuvent être ''faillibles'' : elles peuvent, en principe, être fausses, même si elles bénéficient d’une justification initiale forte. Ce qui les caractérise n’est pas l’impossibilité de l’erreur, mais le fait qu’elles jouissent d’un ''droit épistémique prima facie'' : tant qu’aucune raison contraire ne les met sérieusement en cause, elles sont légitimement tenues pour vraies. Cette version modérée admet également un ''pluralisme inférentiel'' : la justification des croyances non de base peut être transmise non seulement par la déduction, mais aussi par des inférences inductives et par des inférences à la meilleure explication. Les pratiques de généralisation empirique, de mise en hypothèse et de raisonnement analogique sont ainsi pleinement intégrées à l’architecture fondationnaliste. Les croyances de base candidates, dans cette perspective, incluent notamment : * les croyances perceptuelles ordinaires de premier niveau (« Il y a une table devant moi », « J’entends un bruit de pas dans le couloir ») ; * les croyances portant sur nos états mentaux conscients (« J’ai soif », « Je ressens de la tristesse ») ; * certains principes logiques ou mathématiques élémentaires, dont l’évidence rationnelle est robuste, sans être pour autant à l’abri de toute révision possible dans des contextes extrêmes. Cette version modérée paraît plus conforme à notre expérience cognitive réelle : nous accordons volontiers un crédit initial aux données perceptives et aux impressions introspectives, tout en admettant qu’elles puissent être corrigées ou révisées. '''Fondationnalisme minimaliste et pluralisme justificatif''' Une version plus minimale du fondationnalisme se borne à affirmer qu’il existe bien, quelque part dans notre système de croyances, des croyances jouant de fait un rôle fondationnel, sans prétendre que ''toute'' justification doive se ramener, par des enchaînements explicites, à de telles croyances. Elle laisse ainsi davantage de place à des formes mixtes de justification, où des éléments fondationnels et des éléments cohérentistes (cohérence globale du système de croyances) interagissent. Le fondationnalisme se transforme alors en une thèse surtout ''négative'' : il est impossible que toutes nos croyances justifiées soient uniquement dérivées d’autres croyances, sans ancrage aucun dans des croyances ayant un statut plus fondamental. ===== Identifier les croyances de base : critères et phénoménologie ===== '''La justification non inférentielle comme marque distinctive''' Le trait le plus caractéristique des croyances de base est que leur justification est ''non inférentielle''. Le sujet n’a pas besoin de s’appuyer sur d’autres croyances qu’il possède déjà pour avoir le droit de les tenir pour vraies. Une croyance de base peut être justifiée « dès son apparition » dans l’esprit du sujet, pourvu que certaines conditions soient réunies (fiabilité des facultés, absence de défaite, lucidité minimale). '''Critères d’identification''' Reste à préciser comment distinguer, parmi nos croyances, celles qui peuvent légitimement être tenues pour de bonnes candidates fondationnelles. Plusieurs critères sont souvent avancés : * '''L’auto-évidence''' : la croyance apparaît au sujet comme manifestement vraie dès qu’il la comprend ou la saisit ; elle ne réclame aucune preuve supplémentaire pour être raisonnablement acceptée. * '''L’immédiateté''' : la justification n’est pas médiatisée par un raisonnement. Entre le contenu de l’expérience (perceptive ou introspective) et la croyance correspondante, il n’y a pas d’étape argumentative intermédiaire. * '''La stabilité sous l’examen''' : la croyance résiste à la réflexion critique. Lorsqu’on s’interroge sur ses raisons de croire, elle ne se trouve pas affaiblie, mais confirmée dans son statut justificatif. Ces critères ne sont ni nécessaires ni suffisants pris isolément, mais ils contribuent à dessiner le profil des croyances susceptibles d’occuper la base de la structure. '''Les « sembler » phénoménaux comme sources de justification''' Une approche contemporaine, souvent désignée sous le nom de ''conservatisme phénoménal'', ancre les croyances de base dans les ''apparences'' (''seemings'') phénoménales. L’idée est la suivante : lorsque quelque chose ''nous semble'' être le cas – par exemple qu’il y a un arbre devant nous, ou que 2 + 2 = 4 –, ce ''sembler ainsi'' constitue, en l’absence de raisons contraires, une raison suffisante pour croire que les choses sont effectivement ainsi. L’expérience phénoménale confère, de manière par défaut, un droit épistémique à la croyance correspondante. Cette stratégie permet de réconcilier l’exigence fondationnaliste d’une justification non inférentielle avec le constat de notre dépendance à l’égard de ce qui ''apparaît'' à la conscience. Elle soulève cependant une question délicate : comment distinguer les apparences « normales » des apparences trompeuses (illusions, hallucinations) sans réintroduire une demande de justification supplémentaire ? ===== La justification des croyances non de base : inférence et transfert ===== '''L’inférence comme mode de transfert de la justification''' Les croyances non de base reçoivent leur justification grâce à diverses formes d’inférences reliant leur contenu à celui de croyances déjà justifiées. La justification est alors conçue comme une propriété qui ''se transmet'' des prémisses vers la conclusion lorsque certaines conditions logiques et contextuelles sont satisfaites. '''Diversité des formes d’inférence''' Le fondationnalisme modéré reconnaît plusieurs types d’inférences ayant une portée justificatrice : * '''Inférence déductive''' : la conclusion découle nécessairement des prémisses. Si les prémisses sont vraies et parfaitement justifiées, la conclusion ne peut être fausse, et hérite intégralement de leur statut justificatif. * '''Inférence inductive''' : à partir d’un grand nombre de cas observés, on conclut à une régularité générale ou à une anticipation future. L’induction n’offre pas la nécessité, mais une probabilité plus ou moins forte. Le fondationnalisme doit alors accepter une forme de justification graduée : certaines croyances sont plus ou moins fortement soutenues par les données empiriques. * '''Inférence à la meilleure explication''' : parmi plusieurs hypothèses compatibles avec un ensemble de faits, on privilégie celle qui les explique de la manière la plus cohérente, la plus simple et la plus unifiée. Cette forme d’inférence joue un rôle central dans les sciences, où l’on juge les théories à leur pouvoir explicatif global. '''Conditions d’une bonne justification dérivée''' Pour qu’une croyance non de base soit véritablement justifiée dans un cadre fondationnaliste, plusieurs conditions doivent être réunies : * la croyance doit être liée, par une relation inférentielle appropriée (déductive, inductive ou abductive), à un ensemble de croyances déjà justifiées ; * la chaîne inférentielle, si on la prolonge vers le bas, doit aboutir à des croyances de base ; sans ce contact, même l’inférence la mieux formée resterait suspendue dans le vide ; * enfin, il doit exister une ''relation de fondation'' (''basing relation'') correcte : le sujet doit effectivement tenir sa croyance parce qu’il se fonde, de fait, sur les raisons en question. Il ne suffit pas que la croyance ''puisse'' être justifiée par certaines prémisses ; encore faut-il que le processus réel de formation de la croyance reflète cette dépendance aux raisons. Cette dernière exigence permet de distinguer la simple ''disponibilité objective'' d’une justification (il y a des raisons qui pourraient justifier la croyance) de la ''possession effective'' de cette justification par un sujet déterminé. ===== Les atouts du fondationnalisme ===== '''Mettre fin à la régression''' Le premier avantage du fondationnalisme est de proposer une solution claire au problème de la régression infinie : en postulant des croyances de base justifiées, il met un terme au processus de demande de raisons. Au lieu de se perdre dans une exigence de justification sans fin, on admet qu’au niveau des croyances fondamentales, la demande de raisons s’arrête légitimement. '''Rendre compte de nos pratiques ordinaires de justification''' Le fondationnalisme modéré semble aussi bien décrire nos pratiques ordinaires. Lorsqu’on nous demande pourquoi nous croyons telle ou telle chose, nous sommes enclins à remonter jusqu’à des points d’arrêt du type : « Parce que je le vois », « Parce que je le ressens », « Parce que c’est évident », « Parce que je m’en souviens clairement ». Le fondationnalisme donne un cadre théorique à ces arrêts spontanés dans la chaîne des pourquoi. '''Préserver le lien à la vérité''' Dans sa version externaliste, le fondationnalisme insiste sur le fait que les croyances de base sont produites par des mécanismes cognitifs en général fiables. Dès lors, le statut fondationnel de ces croyances n’est pas purement subjectif ; il reflète, au moins en moyenne, une connexion réelle avec la structure du monde. La justification n’est pas seulement une cohérence interne, mais aussi un indice de succès cognitif dans un environnement donné. ===== Objections et difficultés majeures ===== '''Identifier les croyances de base''' Une première difficulté concerne l’identification même des croyances de base. Le fondationnaliste doit être capable de dire, avec un minimum de précision, quelles croyances jouissent de ce statut privilégié. Or, dès que l’on tente de dresser une liste de telles croyances, les controverses surgissent : certains trouvent que la liste est trop restrictive (quasiment aucune croyance ne serait de base), d’autres qu’elle est trop généreuse (on accorderait un privilège injustifié à des croyances en réalité contestables). Le risque est alors d’ériger en « fondations » des convictions que l’on tient pour évidentes simplement parce qu’elles sont profondément enracinées dans une culture ou une époque. '''Les croyances de base demandent-elles elles-mêmes des raisons ?''' Une autre objection est que, psychologiquement et philosophiquement, nous sommes souvent tentés de demander aussi des raisons pour les croyances supposées fondamentales. Si j’affirme : « J’ai mal », il paraît étrange de me demander une preuve. Mais dans d’autres cas, l’appel à l’expérience ou à l’évidence semble moins probant : « Je vois une table » peut être corrigé en « Je vois un trompe-l’œil », « Je crois percevoir une table, mais c’est un hologramme ». Cette possibilité de rectification donne l’impression que même les croyances dites de base doivent pouvoir, à leur tour, être justifiées, ce qui menace de réintroduire la régression. '''Le problème du contenu de l’expérience''' On peut également douter que l’expérience perceptive possède, en elle-même, un contenu suffisamment déterminé pour justifier directement des croyances élaborées sur le monde extérieur. L’expérience fournit-elle une croyance immédiate du type « Il y a une table devant moi » ou seulement quelque chose comme « Il m’apparaît une forme rectangulaire, brune, dans telle portion de mon champ visuel » ? Si l’on adopte la seconde option, l’accès au monde extérieur semble demander des inférences supplémentaires à partir de données plus pauvres ; si l’on adopte la première, l’expérience apparaît déjà saturée de concepts et de jugements, et l’on peut se demander si ce qui était censé être « de base » n’est pas déjà une croyance complexe. '''Le dilemme de Sellars et la critique du « donné »''' Wilfrid Sellars a formulé une critique célèbre du fondationnalisme fondé sur l’idée d’un « donné » expérientiel. Selon lui, ou bien l’expérience a déjà une structure conceptuelle et propositionnelle, et elle tombe alors sous le coup des mêmes exigences de justification que n’importe quelle croyance ; ou bien elle est un simple événement non conceptuel, et il devient mystérieux de comprendre comment un tel événement pourrait, à lui seul, justifier une croyance. Dans les deux cas, l’idée d’un point de départ « donné » et épistémiquement auto-suffisant se trouve gravement mise en cause. '''Le risque de « générosité excessive »''' D’autres critiques, comme Laurence BonJour, ont soutenu que le fondationnalisme contemporain, notamment lorsqu’il se réclame des apparences phénoménales, tend à être trop généreux dans l’attribution de la justification. Si le simple fait que quelque chose nous ''semble'' être le cas suffit à justifier la croyance correspondante, alors un sujet pourrait être massivement dans l’erreur tout en étant néanmoins, d’un point de vue fondationnaliste, largement justifié. L’écart entre justification et vérité risquerait de devenir si grand que la valeur épistémique de la justification s’en trouverait dépréciée. ===== Le fondationnalisme modéré : une position contemporaine défendable ===== Face à ces objections, de nombreux épistémologues contemporains défendent des versions ''modérées'' du fondationnalisme, qui cherchent à conserver l’intuition fondamentale – il doit bien y avoir, quelque part, un point d’arrêt non inférentiel – tout en renonçant aux exigences trop fortes de la certitude absolue ou de l’innocence métaphysique de l’« expérience donnée ». Dans cette perspective, certaines croyances perceptuelles ou introspectives reçoivent une justification initiale, forte mais révisable, qui peut être renforcée ou affaiblie par la suite en fonction d’autres éléments du système de croyances. De plus, la cohérence globale de ce système joue un rôle important : une croyance qui s’insère harmonieusement dans un réseau déjà bien justifié voit son statut renforcé ; une croyance isolée, en tension avec le reste de nos convictions, voit au contraire sa justification affaiblie, même si elle avait, à l’origine, un certain crédit fondationnel. Enfin, le fondationnalisme modéré se laisse souvent combiner avec des intuitions externalistes : les croyances de base ne sont pas seulement privilégiées parce qu’elles ''nous'' paraissent évidentes, mais aussi parce qu’elles sont produites, dans des conditions normales, par des facultés cognitives fiables. La structure hiérarchique de la justification se trouve ainsi articulée à une théorie générale du bon fonctionnement de l’esprit dans son environnement. ===== Conclusion : actualité du fondationnalisme ===== Le fondationnalisme, sous ses formes classiques ou révisées, demeure un acteur central du débat en théorie de la justification. En insistant sur la nécessité de croyances de base justifiées non inférentiellement, il offre une image forte et ordonnée de notre vie cognitive : celle d’un édifice de croyances où certaines d’entre elles jouent le rôle de piliers porteurs. Les principales questions restent cependant ouvertes : existe-t-il véritablement des croyances qui se justifient sans demander d’autres raisons ? Si oui, quelles sont-elles exactement, et comment les distinguer des croyances simplement tenues pour évidentes ? Dans quelle mesure ces croyances de base peuvent-elles être faillibles tout en conservant un statut fondamental ? Les réponses divergent, mais le problème que le fondationnalisme met au jour – la nécessité d’éviter à la fois la régression sans fin, la circularité et l’arbitraire – demeure une contrainte puissante pour toute théorie de la justification. C’est à ce titre que le fondationnalisme conserve, aujourd’hui encore, une place de premier plan dans l’épistémologie contemporaine. ==== 3.4 Structure de la justification : cohérentisme ==== ===== Introduction : le refus des fondations privilégiées ===== Le '''cohérentisme''' propose une conception de la structure de la justification épistémique qui rompt en profondeur avec le fondationnalisme. Alors que le fondationnalisme soutient que la justification doit s’édifier sur une base de croyances fondamentales, dotées d’un statut justificatoire privilégié et non dérivé, le cohérentisme affirme au contraire que '''la justification ne repose pas sur une architecture pyramidale, mais sur un ''ensemble'' de croyances formant un ''système'' : chaque croyance tire son statut justificatoire de ses relations de soutien mutuel avec les autres croyances du système tout entier'''. Aucune croyance ne possède, en droit, un privilège constitutif ; il n’existe pas de « point de départ » auto-justifié qui soutiendrait passivement l’édifice. Une croyance est justifiée dans la mesure où elle s’insère de manière satisfaisante dans un réseau de croyances déjà en place, de telle sorte que l’ensemble forme une structure cohérente, équilibrée et explicativement féconde. Le cohérentisme apporte ainsi une réponse originale au problème de la régression à l’infini : il refuse l’idée que la justification doive se déployer selon une chaîne linéaire qui devrait s’achever soit dans des croyances non justifiées, soit dans des croyances auto-fondées. Pour le cohérentiste, la justification n’est pas une ''ligne'' qui descend vers des fondations, mais un ''tissu'' de relations d’appui réciproques : les croyances se soutiennent mutuellement à l’intérieur d’un système interconnecté, au sein duquel la circularité n’est pas nécessairement vicieuse, pourvu qu’elle s’inscrive dans une structure globale suffisamment cohérente. ===== Le cohérentisme : architecture conceptuelle et principes centraux ===== '''La conception holistique de la justification''' Le cohérentisme s’organise autour d’une thèse directrice : * '''Thèse holistique principale''' : La justification épistémique est, en premier lieu, une propriété du ''système'' de croyances d’un sujet, et seulement de manière dérivée une propriété de croyances singulières. Une croyance n’est pas justifiée en vertu d’une qualité intrinsèque isolée, mais parce qu’elle trouve sa place dans un ensemble de croyances qui, pris globalement, présente un haut degré de cohérence. Ainsi, la question « cette croyance est-elle justifiée ? » ne peut être traitée de façon strictement locale. Elle exige d’examiner comment cette croyance s’articule avec les autres : s’accorde-t-elle avec elles ? les contredit-elle ? permet-elle d’expliquer certaines d’entre elles, ou un ensemble d’expériences ? clarifie-t-elle ou simplifie-t-elle la structure du système ? C’est l’harmonie relative de l’ensemble, et non la solidité isolée de quelques « fondations », qui confère un poids justificatoire. '''L’architecture réticulaire de la justification''' Pour éclairer cette idée, les cohérentistes recourent volontiers à des images architecturales. Le fondationnaliste se représente la justification sur le modèle d’un bâtiment reposant sur des piliers porteurs : les croyances de base jouent le rôle de fondations, tandis que les autres croyances, situées à des niveaux supérieurs, dépendent d’elles sans leur rendre en retour un soutien justificatoire. Le cohérentiste préfère une autre image, plus dynamique : celle d’une '''voûte''' ou d’un '''réseau'''. Dans une voûte de pierres appareillées, aucune pierre unique ne joue le rôle de fondation absolue ; chaque pierre soutient les pierres voisines et se trouve elle-même maintenue par elles. La stabilité de l’ensemble ne résulte pas de la solidité d’un bloc premier, mais d’un équilibre de forces distribuées dans tout l’arc. De même, dans un réseau de croyances, chaque élément reçoit un soutien du système et contribue en retour à sa cohésion ; l’édifice tient parce que les relations sont bien ajustées, non parce qu’un socle ultime serait inébranlable. Cette métaphore interdit l’idée d’une croyance qui serait ''justifiée par avance'' en dehors de tout contexte : ce qui importe est la place que la croyance occupe dans la trame de nos engagements, et les ajustements qu’elle impose ou permet au système dans son ensemble. ===== La remise en cause cohérentiste de l’argument de la régression ===== '''Révision des prémisses de la régression à l’infini''' L’argument fondationnaliste classique de la régression soutient qu’une croyance justifiée doit être fondée sur une autre croyance déjà justifiée ; si chaque croyance devait ainsi en présupposer une autre, on obtiendrait soit une régression infinie, soit un cercle, soit un arrêt arbitraire dans l’injustifié. D’où la conclusion : il faut bien des croyances de base, qui ne tiennent pas leur justification d’autres croyances. Le cohérentiste ne conteste pas que, dans nos pratiques de justification, nous invoquions certaines croyances pour en soutenir d’autres. Il refuse cependant l’hypothèse implicite selon laquelle la justification devrait être pensée selon le modèle d’une ''chaîne unidirectionnelle'' : A justifie B, B justifie C, etc. Il soutient au contraire que la justification a fondamentalement une structure ''réticulaire'' et ''circulaire'' : * une croyance peut renforcer la crédibilité d’une autre, tout en recevant d’elle un appui en retour ; * la « circularité » n’est pas en soi un vice, si elle s’inscrit dans un ensemble suffisamment riche, diversifié et intégré pour que le système, dans son ensemble, rende raison de nos expériences et reste ouvert à la révision. L’argument fondationnaliste présuppose que tout cercle justificatoire est désespérément suspect. Le cohérentiste répond qu’il n’en est pas ainsi : un petit cercle isolé de deux ou trois croyances arbitraires est certes épistémiquement stérile, mais un vaste réseau, où les liens explicatifs, inductifs et conceptuels sont multiples et croisés, peut parfaitement produire, à l’échelle du système, une justification satisfaisante. '''La circularité dans un cadre systémique''' La circularité justificatoire n’est acceptable, selon le cohérentiste, qu’à certaines conditions exigeantes. Il ne s’agit pas de dire que « A justifie B et B justifie A » serait suffisant. Pour que la circularité ne soit pas purement illusoire, il faut que : * le système comporte un grand nombre de croyances distinctes, portant sur des domaines variés ; * ces croyances soient reliées par des liens conceptuels, explicatifs et inductifs riches ; * le système soit capable d’intégrer des données nouvelles, de corriger des erreurs locales, de se transformer sans perdre sa cohésion d’ensemble. Ce n’est donc pas la circularité en tant que telle qui fonde la justification, mais la capacité du système circulaire à organiser, expliquer et anticiper un large spectre de croyances et d’expériences, tout en restant relativement stable et révisable. Dans cette perspective, la régression n’est plus un gouffre à éviter, mais la marque de la complexité normale d’un tissu de raisons qui se soutiennent mutuellement. ===== La notion multidimensionnelle de cohérence : au-delà de la simple consistance ===== '''La cohérence ne se réduit pas à l’absence de contradiction''' Une difficulté immédiate pour le cohérentisme consiste à préciser ce qu’il entend par « cohérence ». On pourrait croire, de manière simpliste, qu’un ensemble de croyances est cohérent s’il ne contient pas de contradiction formelle : aucune croyance ne doit logiquement impliquer la négation d’une autre. Or cette condition de consistance, bien que nécessaire, est manifestement insuffisante. En effet, un ensemble de croyances peut être parfaitement consistant tout en étant épistémiquement misérable. Une collection de propositions disparates, sans aucun lien thématique ni explicatif, pourrait être logiquement non contradictoire et pourtant dépourvue de toute cohérence au sens fort. La cohérence justificatrice véritable doit donc impliquer plus que l’absence de contradiction ; elle renvoie à une structure d’ensemble intelligible et articulée. '''Les dimensions de la cohérence justificatrice''' Les cohérentistes contemporains distinguent plusieurs dimensions complémentaires de la cohérence : * '''Consistance logique''' : l’ensemble ne doit pas contenir de contradictions manifestes. C’est une exigence minimale : un système où l’on affirme à la fois ''p'' et ''non-p'' perd immanquablement de sa valeur justificatrice. * '''Articulation conceptuelle''' : les croyances doivent entretenir des liens conceptuels intelligibles entre elles. Elles doivent s’ordonner selon des relations de spécialisation, de généralisation, de précision, de conséquence ou d’incompatibilité conceptuelle qui confèrent à l’ensemble une structure compréhensible, plutôt qu’un simple inventaire de propositions juxtaposées. * '''Cohérence explicative''' : un système cohérent est capable d’expliquer un grand nombre de croyances particulières et de données d’expérience par un petit nombre de principes plus généraux. Ainsi, la croyance que « les corps tombent vers le sol » et celle que « les planètes décrivent des trajectoires elliptiques » trouvent une cohérence accrue lorsqu’elles sont expliquées par une théorie commune de la gravitation. La capacité d’un ensemble de croyances à rendre intelligibles de multiples phénomènes constitue une dimension décisive de la cohérence. * '''Soutien inductif et probabiliste''' : les croyances d’observation, les généralisations empiriques et les hypothèses théoriques doivent se renforcer mutuellement. Plus un système parvient à prédire avec succès des observations nouvelles et à intégrer les résultats expérimentaux, plus sa cohérence probabiliste augmente. La cohérence n’est pas seulement logique : elle est également ''inductive'' et ''confirmative''. * '''Simplicité et économie''' : à contenu explicatif égal, un système qui recourt à moins d’hypothèses ad hoc, qui évite les complications inutiles et qui unifie les phénomènes sous des principes sobres, est réputé plus cohérent qu’un système proliférant en explications disparates. * '''Stabilité et capacité de révision''' : un système cohérent ne s’effondre pas sous l’ajout d’une information nouvelle ; il peut au contraire absorber des corrections locales en réaménageant ses croyances périphériques, tout en conservant un noyau stable et intelligible. Cette capacité d’autorévision contrôlée est elle-même un indice de cohérence. Ainsi comprise, la cohérence n’est pas un critère monolithique, mais un faisceau de propriétés structurelles qui, combinées, confèrent un poids justificatoire au système de croyances. ===== Variantes du cohérentisme ===== '''Cohérentisme holiste classique''' Le '''cohérentisme holiste''' soutient que le statut justificatoire d’une croyance dépend exclusivement de sa place dans la totalité du système de croyances d’un sujet. Pour savoir si une croyance donnée est justifiée, il faudrait en principe se demander comment elle s’intègre à l’ensemble complet : quelles modifications elle impose, quelles tensions elle crée ou résout, quelles explications nouvelles elle permet ou interdit. Laurence BonJour, par exemple, défend un cohérentisme de ce type en insistant sur le caractère ''symétrique'' et ''réciproque'' des relations justificatrices : aucune croyance ne joue, par nature, le rôle de point de départ indiscutable ; la justification naît de l’organisation d’ensemble, non d’un privilège originel concédé à certains énoncés.<ref>{{Ouvrage|lang=en|prénom=Laurence|nom=BonJour|titre=The Structure of Empirical Knowledge|lieu=Cambridge (Mass.)|éditeur=Harvard University Press|année=1985}}</ref> '''Cohérentismes modérés et approches hybrides''' D’autres auteurs défendent des formes plus ''modérées'' de cohérentisme. Certains soutiennent qu’il est possible de raisonner de manière plus locale : de ''petits sous-systèmes'' de croyances, fortement interconnectés et relativement autonomes, peuvent avoir une pertinence justificatrice propre, sans qu’il soit toujours nécessaire de prendre en vue l’ensemble du système. D’autres encore, comme Susan Haack, proposent des positions hybrides – parfois qualifiées de « fondhérentistes » – qui combinent des éléments fondationnalistes et cohérentistes : il existe bien des croyances d’observation disposant d’un statut privilégié, mais leur contribution justificatrice ne se comprend qu’à l’intérieur d’un réseau plus large de dépendances mutuelles.<ref>{{Ouvrage|lang=en|prénom=Susan|nom=Haack|titre=Evidence and Inquiry. Towards Reconstruction in Epistemology|lieu=Oxford|éditeur=Blackwell|année=1993}}</ref> Ces positions témoignent de la plasticité du schème cohérentiste, susceptible de diverses inflexions. ===== Les mérites philosophiques du cohérentisme ===== '''Une réponse originale au problème de la régression''' Le premier mérite du cohérentisme est de proposer une issue qui ne passe ni par une régression infinie, ni par un arrêt dogmatique, ni par une circularité superficielle. En situant la justification au niveau du système, il considère la régression non comme une menace à conjurer, mais comme l’expression de l’intrication normale des raisons : il est naturel que la plupart de nos croyances s’appuient sur d’autres, qui à leur tour renvoient à un réseau plus large, sans que cela oblige à désigner un commencement absolu. '''Un modèle fidèle de la pratique rationnelle et scientifique''' Le cohérentisme apparaît également plausible lorsqu’on examine la pratique réelle des sciences. Les théories scientifiques ne se présentent pas comme des édifices parfaitement hiérarchisés reposant sur quelques énoncés indubitables ; elles forment plutôt des ensembles d’hypothèses, de lois, de modèles, d’énoncés d’observation et de principes méthodologiques qui se soutiennent mutuellement. Lorsqu’un résultat expérimental contredit une prédiction, on ne renonce pas automatiquement au « fondement » le plus élémentaire ; on examine l’ensemble : l’instrumentation, les hypothèses auxiliaires, les approximations de calcul, etc. Une théorie gagne en justification non parce qu’elle se rapproche d’un socle inébranlable, mais parce qu’elle s’intègre de mieux en mieux à un réseau de croyances interconnectées, explicatives et prédictives. '''Un schème adapté à la révision continue des croyances''' Enfin, le cohérentisme rend compte de la manière dont nous révisons effectivement nos croyances. Nous ne partons pas d’un fondement absolu pour en dériver mécaniquement toutes les autres croyances ; nous ajustons sans cesse notre système à la lumière de nouvelles informations, en renonçant parfois à des convictions profondes lorsque leur maintien engendrerait trop de tensions avec le reste de ce que nous tenons pour vrai. La rationalité épistémique apparaît alors comme un travail permanent d’''ajustement'' et de ''rééquilibrage'' du système, ce que le modèle cohérentiste embrasse naturellement. ===== Objections majeures au cohérentisme ===== '''L’objection de l’isolement''' La critique la plus célèbre est l’'''objection de l’isolement''' : un système de croyances pourrait être parfaitement cohérent tout en étant entièrement faux et sans rapport avec la réalité. On peut imaginer un sujet enfermé dans une simulation parfaite ou trompé par un démon cartésien : toutes ses croyances sur son environnement, son corps, l’histoire du monde, se soutiennent mutuellement, expliquent ses expériences apparentes, prédisent correctement ce qu’il « verra » dans la simulation ; et pourtant, rien de tout cela ne correspond au monde réel. Si la seule cohérence intra-systémique suffisait à fonder la justification, il faudrait reconnaître à ce sujet des croyances pleinement justifiées, alors même qu’il vit dans une illusion généralisée. Cette conséquence paraît contre-intuitive : la justification semble exiger non seulement une bonne organisation interne des croyances, mais aussi un certain ''ancrage'' dans le réel. '''Permissivité excessive et pluralité de systèmes cohérents''' Une objection proche souligne le risque de '''permissivité''' : plusieurs systèmes de croyances distincts, incompatibles entre eux, pourraient chacun présenter un haut degré de cohérence interne. Rien, dans la conception purement cohérentiste, ne garantirait a priori qu’un seul système soit justifié. Si des ensembles de croyances radicalement divergents – portant par exemple sur la structure de l’univers, l’existence de certaines entités, ou les normes morales fondamentales – peuvent tous atteindre une forte cohérence interne, le cohérentisme semble condamné à admettre une pluralité de systèmes également justifiés, sans critère pour trancher entre eux. Il risquerait alors de glisser vers une forme de relativisme épistémique. '''Le problème de l’« entrée » de l’expérience''' Une autre difficulté, souvent relevée, concerne le statut de l’'''expérience''' dans un schème cohérentiste. Si seules les croyances peuvent justifier des croyances, comment comprendre le rôle des données sensibles, des impressions perceptives, des affects ? Le cohérentiste répond généralement que l’expérience intervient sous la forme de croyances d’observation (« il me semble voir une table », « j’éprouve une douleur vive »), qui appartiennent au système et y occupent une place particulière : elles sont plus fermement ancrées, plus résistantes à la révision que d’autres. Mais certains critiques objectent que, si l’on admet ainsi des « croyances d’observation » privilégiées, on se rapproche dangereusement d’un fondationnalisme déguisé ; et si l’on refuse tout privilège à ces croyances, on ne comprend plus comment l’expérience ''contraint'' effectivement nos théories. C’est le problème dit de l’''entrée'' (''input problem'') du cohérentisme.<ref>{{Ouvrage|lang=en|prénom=Keith|nom=Lehrer|titre=Theory of Knowledge|lieu=London|éditeur=Routledge|année=1990}}</ref> ===== Réponses cohérentistes contemporaines ===== Les cohérentistes ont développé diverses stratégies pour répondre à ces objections. Certains insistent sur le fait que l’expérience n’est pas un élément extérieur à la sphère des croyances, mais qu’elle se manifeste à travers des croyances d’un type particulier, fortement reliées à nos sensations et difficilement révisables sans raison puissante. Ces croyances d’observation, bien qu’elles ne soient pas infaillibles, jouent un rôle de ''points d’ancrage'' pour le système : lorsque des tensions apparaissent, c’est d’abord la périphérie théorique qui est remise en cause, et non ces croyances immédiatement liées à la perception. D’autres élaborent des conceptions '''naturalistes''' de la cohérence : la cohérence d’un système de croyances n’est plus seulement un critère logique interne, mais se mesure à sa capacité à guider efficacement l’action, à s’accorder avec les méthodes des sciences empiriques, à produire des prédictions fructueuses. La cohérence inclut alors, en quelque sorte, la contrainte du réel dans sa définition même. Enfin, plusieurs auteurs reconnaissent les limites du cohérentisme « pur » et adoptent des positions '''mixtes''', dans lesquelles la cohérence joue un rôle central mais non exclusif : elle vient compléter d’autres sources de justification (expérience perceptive, mémoire, témoignage), sans s’y substituer entièrement. C’est la combinaison d’un certain ancrage expérientiel et d’une forte cohérence interne qui fonde, en dernière analyse, le caractère raisonnable de nos croyances. ===== Conclusion : la place du cohérentisme dans l’épistémologie contemporaine ===== Le cohérentisme demeure aujourd’hui l’une des grandes théories concurrentes du fondationnalisme pour penser la structure de la justification. Il met en valeur le caractère systématique de nos croyances, l’importance des liens explicatifs et inductifs qui les unissent, et la dimension dynamique de la rationalité, comprise comme révision incessante d’un réseau de convictions plutôt que comme déduction à partir de fondements intangibles. Les objections classiques – en particulier l’isolement possible d’un système cohérent par rapport à la réalité, et la difficulté d’intégrer l’expérience comme source de contrainte – n’ont pas été définitivement levées. Mais les efforts pour y répondre ont enrichi l’analyse de la cohérence elle-même et favorisé l’émergence de positions hybrides où la cohérence, loin d’être un critère unique, devient l’une des vertus épistémiques décisives d’un ensemble de croyances. Le débat entre fondationnalisme et cohérentisme, loin d’être clos, continue ainsi de structurer l’épistémologie contemporaine et de nourrir la réflexion sur la manière dont nos croyances peuvent, ou non, être légitimement tenues pour justifiées. ==== 3.5 L'infinitisme : l'acceptation de la régression justificatoire à l'infini ==== ===== Introduction : une troisième voie face à la régression de la justification ===== L’infinitisme est une position théorique audacieuse et largement contre-intuitive qui se présente comme une alternative à la fois au fondationnalisme et au cohérentisme. Alors que le fondationnalisme soutient que la régression de la justification doit s’interrompre dans des croyances de base auto-justifiées, et que le cohérentisme affirme que cette régression peut légitimement prendre la forme d’un réseau circulaire de croyances se soutenant mutuellement, l’infinitisme propose une troisième voie : accepter que la régression justificatoire se poursuive sans fin et reconnaître que cette infinité non répétitive ''constitue'' précisément la structure adéquate de la justification. Pour l’infinitiste, une croyance ne jouit d’une véritable justification que si elle s’inscrit dans une chaîne potentiellement ''infinie et non répétitive'' de raisons justificatrices, disponibles en principe pour le sujet. L’idée centrale est que la demande de justification ne saurait être légitimement interrompue ni par un arrêt arbitraire dans des « fondements » ultimes, ni par une circularité où l’on reviendrait, de manière plus ou moins déguisée, au point de départ. Cette position se présente explicitement comme une réponse à ce que Peter D. Klein appelle le ''problème de l’amélioration'' de la justification : lorsqu’une croyance est mise en question, de quelle manière une raison supplémentaire peut-elle véritablement améliorer son statut justificatoire ? L’infinitiste répond : seule une chaîne illimitée de raisons nouvelles, jamais répétées, permet d’améliorer indéfiniment la justification sans sombrer ni dans l’arbitraire fondationnel ni dans la circularité cohérentiste. Le mouvement sans fin de la demande de raison ne constitue plus un « défaut » de notre système de croyances, mais devient au contraire sa structure normative appropriée. ===== Les deux principes axiomatiques de l’infinitisme épistémique ===== '''Le Principe de Non-Circularité (PNC)''' L’infinitisme repose sur deux principes de base qui organisent l’ensemble de la théorie. Le premier est le Principe de Non-Circularité. On peut le formuler ainsi : si un sujet S possède une véritable justification pour une croyance B, alors aucune croyance B* qui intervient à quelque niveau que ce soit dans la chaîne justificatrice de B ne peut être identique à B, ni logiquement équivalente à B, ni constituer une partie d’une conjonction logiquement équivalente à B. En d’autres termes, une croyance ne peut jamais faire partie de sa propre généalogie justificatoire ; la circularité – directe ou indirecte – est épistémiquement proscrite. Ce principe traduit une intuition profondément ancrée : la justification circulaire, loin d’apporter un gain cognitif, revient à tourner en rond. Si je prétends justifier la croyance « le feu produit une chaleur intense » par l’énoncé « j’ai observé à de nombreuses reprises que le feu produit de la chaleur », et que, sous la pression d’une demande supplémentaire, je fais finalement appel, d’une manière ou d’une autre, à la croyance initiale pour justifier la croyance perceptive elle-même, je n’ai pas véritablement avancé. Je me contente de décrire la même chose sous des formulations différentes ; je manque le type de progression justificatoire qu’exige l’enquête rationnelle. Le PNC généralise cette intuition et l’érige en norme : l’amélioration de la justification requiert que l’on passe à des raisons réellement nouvelles et distinctes. '''Le Principe d’Amélioration par Raisons Additionnelles (PARA)''' Le second principe, le Principe d’Amélioration par Raisons Additionnelles, complète le premier. Il affirme que, pour toute croyance justifiée d’un sujet S, il existe en principe une chaîne de raisons telle que chaque élément de la chaîne justifie entièrement le précédent, et que cette chaîne est, par nature, ouverte à une extension indéfinie. Aucune raison isolée n’est, à elle seule, définitivement et de manière autonome suffisante ; chaque raison appelle à son tour une nouvelle raison qui en soutient la valeur justificatrice. Ce principe exprime l’idée que, dès lors que l’on admet qu’''une'' raison peut améliorer la justification d’une croyance, rien ne justifie rationnellement d’assigner un point d’arrêt nécessaire à ce processus. Si R justifie P, on peut toujours demander ce qui justifie R ; si une nouvelle raison R* vient justifier R, on pourra à son tour interroger le statut de R*, et ainsi de suite. Si l’on prend au sérieux la normativité de cette exigence de raison supplémentaire, alors il n’existe pas de « dernier mot » justificatoire qui serait rationnellement à l’abri de toute demande de fondement. Le PARA systématise cette idée : la logique interne de la justification entraîne une ouverture structurelle vers une régression à l’infini. ===== La structure architectonique infinitiste de la justification ===== '''La chaîne infinie et non répétitive : cœur du modèle''' De la combinaison du PNC et du PARA découle la thèse infinitiste centrale : pour qu’une croyance soit véritablement justifiée pour un sujet donné, il faut qu’il existe, en principe, une chaîne ''infinie et non répétitive'' de raisons, telle que chaque raison justifie la précédente et qu’aucune ne réapparaisse dans la série. La structure justificatoire adoptée par l’infinitisme a donc la forme d’une progression sans terme. On peut se la représenter ainsi : la croyance initiale P est justifiée par une raison r<sub>1</sub>. Cette raison r<sub>1</sub> reçoit à son tour sa justification de r<sub>2</sub>, r<sub>2</sub> est justifiée par r<sub>3</sub>, r<sub>3</sub> par r<sub>4</sub>, et ainsi de suite, sans fin. La chaîne r<sub>1</sub>, r<sub>2</sub>, r<sub>3</sub>, r<sub>4</sub>, … n’est pas seulement potentiellement très longue : elle est, en droit, illimitée, et aucun maillon n’y fait retour. Chaque raison a pour rôle d’améliorer la justification de la raison immédiatement antérieure, et l’ensemble de la structure confère à la croyance de départ un statut justificatoire qui ne cesse de s’accroître à mesure que l’on progresse dans la chaîne. Contrairement au fondationnaliste, l’infinitiste ne cherche pas un point d’arrêt privilégié qui serait, par nature, « auto-justifié ». Contrairement au cohérentiste, il refuse que l’on puisse revenir, d’une manière ou d’une autre, à des croyances déjà convoquées, même si c’est sous une forme reformulée ou intégrée dans un réseau global. La justification, pour lui, est intrinsèquement dynamique : elle consiste dans la possibilité de prolonger indéfiniment une série de raisons nouvelles. '''L’argument infinitiste contre le trilemme d’Agrippa''' Le trilemme d’Agrippa met en lumière trois issues possibles pour la régression des raisons : la régression infinie, la circularité, ou l’arrêt arbitraire. Le fondationnalisme assume l’arrêt arbitraire dans des croyances de base injustifiées mais supposées indubitables ; le cohérentisme assume la circularité en faisant valoir la force d’un système de croyances mutuellement soutenues ; l’infinitisme, quant à lui, assume la régression à l’infini et la réhabilite comme structure normative. Pour Peter D. Klein, le véritable problème n’est pas la régression en tant que telle, mais le manque d’amélioration justificatoire. Un arrêt arbitraire dans des croyances de base ne permet pas d’expliquer en quoi ces croyances, plutôt que d’autres, devraient jouir d’un statut privilégié. De même, une circularité, même large, semble toujours trahir une forme de complaisance : on finit par se justifier à partir de ce que l’on présuppose déjà. L’infinitisme se présente alors comme la seule position qui, tout en prenant au sérieux l’exigence d’une amélioration constante, évite à la fois l’arbitraire et la circularité. La régression à l’infini n’est plus un scandale théorique, mais la seule réponse cohérente à la normativité de la demande de raison. ===== L’accessibilité en puissance des raisons infinies : un problème psychologique central ===== '''Le problème de l’accessibilité psychologique''' L’objection la plus immédiate semble insurmontable : comment un sujet humain, fini et limité, pourrait-il ''posséder'' une justification qui dépend d’une infinité de raisons ? Il serait absurde de prétendre qu’un sujet garde présentes à l’esprit, à chaque instant, une quantité illimitée d’éléments justificatifs articulés. L’infinitisme répond en distinguant l’accessibilité ''actuelle'' de l’accessibilité ''en puissance'' ou dispositionnelle. Il n’est nullement requis que le sujet ait actuellement en tête, de manière consciente et explicite, l’ensemble des raisons composant la chaîne infinie. Ce qui est requis, c’est que pour tout maillon de la chaîne, le sujet soit, en principe, capable de fournir une raison supplémentaire si la situation épistémique le demande. Autrement dit, l’ensemble de la chaîne n’est pas ''effectivement'' parcouru, mais le sujet possède la ''capacité'' de prolonger la série chaque fois qu’une raison nouvellement produite est mise en cause. Cette distinction est essentielle : l’infinitisme ne mise pas sur un stock infini de contenus présents dans la conscience, mais sur une compétence cognitive, une disposition à produire des raisons supplémentaires lorsque les conditions de la discussion ou de l’enquête l’exigent. La justification repose alors, non sur l’énumération effective d’une suite infinie, mais sur l’aptitude, toujours reconductible, à fournir de nouvelles raisons. '''L’analogie avec d’autres capacités cognitives''' L’infinitiste invoque volontiers une analogie avec d’autres domaines cognitifs. Ainsi, un mathématicien qui maîtrise les axiomes de l’arithmétique ne détient pas actuellement, dans sa conscience, toutes les conséquences possibles de ces axiomes. Pourtant, on estime qu’il ''sait'' qu’il pourrait, pas à pas, dériver une infinité de théorèmes à partir de ce petit ensemble de principes de base. Ce qu’il possède, ce n’est pas un inventaire achevé de résultats, mais une capacité réglée à en produire indéfiniment de nouveaux. De manière similaire, l’agent épistémique ne ''détient'' pas une série infinie de raisons déjà explicitées, mais il possède une compétence rationnelle qui lui permettrait, à chaque fois que l’on met en cause une raison, d’en articuler une autre plus profonde. La justification infinitiste repose donc sur une structure dispositionnelle : elle est liée à ce que le sujet pourrait, en droit, produire comme raisons, et non à ce qu’il a, de fait, déjà formulé. ===== Les avantages philosophiques et l’attrait théorique de l’infinitisme ===== '''L’évitement du trilemme d’Agrippa''' L’un des principaux attraits de l’infinitisme est sa capacité à rendre compte, de manière unifiée, des exigences que le trilemme d’Agrippa met en évidence. En refusant tout arrêt arbitraire, il honore l’idée qu’aucune croyance ne doit être immunisée contre la demande de justification. En interdisant la circularité, il maintient l’exigence de progressivité et de non-redondance dans la chaîne des raisons. En assumant l’ouverture infinie du processus, il donne un contenu précis à la notion de ''perfectibilité'' de la justification : une croyance peut toujours être davantage justifiée par l’ajout de nouvelles raisons. De ce point de vue, l’infinitisme fournit une image très exigeante de la rationalité : une rationalité qui ne se contente jamais de ses acquis et qui refuse absolument toute clôture dogmatique. C’est cette radicalité critique qui fait la force séduisante du modèle pour certains théoriciens, même si elle en accroît en retour le coût psychologique et pratique. '''L’amélioration progressive de la justification''' Un autre mérite de l’infinitisme, tel que le met en avant Klein, est de rendre intelligible l’idée d’une ''amélioration graduelle'' de la justification. Dans notre pratique ordinaire, nous considérons spontanément qu’une croyance est d’autant mieux justifiée que nous pouvons invoquer, à son appui, des raisons plus nombreuses, plus variées, plus indépendantes les unes des autres. Si, face à la contestation d’une croyance, je fournis une première raison, puis une seconde qui vient justifier la pertinence de la première, puis une troisième qui renforce la deuxième, il semble bien que la position justificatoire globale de ma croyance de départ s’en trouve réellement consolidée. L’infinitisme systématise cette intuition : chaque raison additionnelle améliore le statut épistémique de la croyance de départ. Il n’existe pas de « plafond » au-delà duquel la justification deviendrait absolument complète et insusceptible d’augmentation. L’infini ne désigne pas un point que l’on atteindrait, mais la structure ouverte d’un processus d’amélioration sans terme. Ce faisant, l’infinitisme capte, de manière théorique, une dimension importante de notre expérience concrète de la discussion et de l’argumentation. ===== Les objections majeures adressées à l’infinitisme ===== '''L’objection de l’accessibilité psychologique''' La critique la plus classique insiste sur ce qui semble être une exigence psychologiquement impossible : si la justification exige une chaîne infinie de raisons, alors, dans les faits, aucune croyance humaine ne serait jamais réellement justifiée. Même en admettant la distinction entre accessibilité actuelle et dispositionnelle, il paraît difficile de donner un contenu clair à l’idée qu’un sujet est ''en puissance'' capable de prolonger indéfiniment une chaîne justificatoire : aucune capacité humaine n’est véritablement illimitée, et l’appel à une disposition infinie peut apparaître comme une fiction vide. Les adversaires de l’infinitisme soutiennent que l’on finit ainsi par vider la notion de possession de justification de son sens ordinaire : on en vient à dire que le sujet ''possède'' des raisons qu’il ne pourrait jamais, de fait, énoncer ou même esquisser. La justification se détache alors dangereusement de ce que les agents sont réellement capables de faire dans l’enquête et le dialogue, et risque de devenir une construction purement théorique, sans prise sur notre pratique cognitive effective. '''L’objection de l’inadéquation aux cas ordinaires''' Une autre objection fortement intuitive part des exemples les plus élémentaires de croyances perceptives. Lorsque je crois, en regardant devant moi, qu’« il y a un mur bleu à quelques mètres », il semble extrêmement artificiel de dire que ma croyance n’est justifiée que si une chaîne infinie de raisons est, en principe, disponible. De manière spontanée, nous considérons qu’une perception claire et non trompeuse suffit, dans un contexte ordinaire, à justifier la croyance correspondante. L’infinitisme, s’il est pris au pied de la lettre, paraît contraint d’affirmer que cette croyance n’est pas, à proprement parler, justifiée, tant que l’on ne peut pas greffer sur elle une structure justificatoire ouverte à l’infini. Il se trouve ainsi en tension avec la pratique épistémique commune, qui attribue volontiers un haut degré de justification à ce type de croyances sans exiger la moindre chaîne de ce genre. Pour beaucoup de philosophes, cette conséquence constitue une réduction à l’absurde de la thèse infinitiste. '''L’objection des chaînes concurrentes et du risque de symétrie''' Enfin, certains critiques avancent que la simple existence d’une chaîne infinie de raisons ne suffit pas à garantir la valeur épistémique d’une croyance, en particulier lorsque des croyances opposées peuvent, en principe, être soutenues par des chaînes analogues. Si l’on peut imaginer une série de raisons infinies à l’appui de P et une autre série infinie à l’appui de non-P, la structure infinitiste, prise isolément, ne permet pas de trancher entre ces deux ensembles concurrentiels. L’objection vise ici à montrer que l’infinitisme, lorsqu’il se présente comme théorie ''pure'' de la structure justificatoire, doit être complété par d’autres critères (réalisme de la connexion à la vérité, fiabilité des processus de formation des croyances, cohérence globale du système, etc.) pour éviter de considérer comme également justifiables des croyances manifestement incompatibles. Ce point ouvre la voie à des versions ''mixtes'' de l’infinitisme. ===== Variantes et raffinements de l’infinitisme ===== '''Infinitisme pur et infinitisme mixte''' On peut distinguer un ''infinitisme pur'', qui fait de la présence d’une chaîne infinie et non répétitive de raisons une condition à la fois nécessaire et suffisante de la justification, et un ''infinitisme mixte'', qui maintient le caractère nécessaire de cette chaîne mais y ajoute d’autres exigences. L’infinitisme mixte admet par exemple que les raisons doivent former un ensemble suffisamment cohérent, être reliées de manière appropriée aux faits, ou provenir de processus cognitifs fiables. Cette forme modérée cherche à préserver l’intuition fondamentale de l’infinitisme – à savoir que la demande de nouvelles raisons ne se clôt jamais – tout en intégrant les leçons d’autres approches (fiabilisme, cohérentisme, réalisme épistémique). Elle reconnaît que la structure infinitiste ne suffit pas, à elle seule, à capturer toute la normativité de la justification. '''Infinitisme contextuel''' Une autre tentative de réponse aux objections consiste à proposer un ''infinitisme contextuel''. Selon cette variante, ce n’est pas un nombre déterminé de raisons qui est exigé dans l’absolu, mais un schéma structurel dont la portée dépend des contextes. Dans les situations ordinaires, comme certaines croyances perceptives élémentaires, les exigences sont relativement faibles : une courte chaîne de raisons – éventuellement en grande partie implicites – peut être tenue pour suffisante. En revanche, dans les contextes de contestation sérieuse, de désaccord argumenté, ou de recherche scientifique approfondie, la demande de raisons devient plus pressante, et la chaîne justificatoire doit pouvoir être prolongée beaucoup plus loin. L’infinité ne serait alors pas une condition toujours actuellement requise, mais une ''limite régulatrice'' : elle exprimerait l’idée que, pour toute demande de raison recevable, le sujet doit pouvoir, en principe, poursuivre l’enquête, sans que la structure de la justification prévoie jamais un point d’arrêt absolu. L’infini est alors compris comme l’horizon d’un processus, non comme une propriété actualisée de l’activité cognitive. ===== Conclusion : une position marginale mais théoriquement stimulante ===== L’infinitisme demeure une position minoritaire en épistémologie contemporaine, mais il s’agit d’une position élaborée, systématique et philosophiquement stimulante. En prenant au sérieux jusqu’au bout l’exigence de raison supplémentaire, il offre une image exigeante de la rationalité, où la justification ne se laisse jamais figer dans un ensemble fini de fondements définitivement à l’abri de la critique. Ses forces tiennent principalement à la manière dont il affronte le trilemme d’Agrippa et à sa capacité à conceptualiser l’amélioration graduelle de nos justifications au fil de l’enquête. Ses faiblesses résident dans le coût psychologique et pratique de ses exigences, dans son apparente incompatibilité avec nos jugements ordinaires sur les cas de justification les plus simples et, parfois, dans son besoin d’être complété par d’autres critères pour départager des chaînes de raisons concurrentes. Le débat entre fondationnalisme, cohérentisme et infinitisme, loin de se réduire à une querelle technique, engage en réalité trois conceptions profondes de ce que signifie être ''rationnel'': accepter certains points de départ comme donnés, valoriser la cohérence globale d’un système de croyances, ou bien reconnaître que la demande de raison reconductible à l’infini est l’expression la plus exigeante de l’idéal critique de la connaissance. À ce titre, l’infinitisme, même s’il n’emporte pas l’adhésion, contribue puissamment à éclairer les tensions internes de notre conception de la justification. ==== 3.6 Les approches hybrides et alternatives : dépassement des tripartitions classiques ==== ===== Introduction : au-delà de la tripartition fondationnalisme–cohérentisme–infinitisme ===== Les débats épistémologiques sur la structure de la justification ont longtemps été organisés autour de trois grandes familles de positions : le fondationnalisme, le cohérentisme et l’infinitisme. Cette tripartition a l’avantage de clarifier les options théoriques, mais elle tend aussi à rigidifier le paysage conceptuel, comme si toute théorie de la justification devait nécessairement se ranger dans l’un de ces trois camps exclusifs. Or, au cours des dernières décennies, de nombreux auteurs ont cherché à dépasser cette alternative étroite en élaborant des approches ''hybrides'' et ''alternatives'' qui refusent de se laisser enfermer dans ce schéma. Ces approches partent souvent d’un constat commun : chacune des trois théories classiques met en lumière une dimension légitime et importante de la justification, mais chacune, prise isolément, se heurte à des difficultés qu’elle ne parvient pas à résoudre sans faire appel à des idées empruntées aux autres. Plutôt que de défendre une position « pure » contre toutes les autres, ces théories hybrides s’attachent à combiner, dans un cadre plus souple, les apports conceptuels essentiels des différentes traditions. Elles ouvrent ainsi des voies nouvelles pour sortir de certaines impasses récurrentes du débat. On peut distinguer, parmi ces tentatives, plusieurs orientations principales : un ''fondationnalisme mitigé'' ou modéré, qui cherche à articuler croyances de base et cohérence globale ; la ''théorie des vertus épistémiques'', qui déplace l’accent des croyances vers les agents et leurs dispositions intellectuelles ; le ''pragmatisme épistémologique'', qui relie étroitement justification et pratique ; l’''épistémologie féministe'' et l’''épistémologie sociale'', qui introduisent la dimension collective et politique de la connaissance ; enfin, diverses formes de synthèses explicites entre fondationnalisme, cohérentisme et infinitisme, ainsi que des formes de ''pluralisme contextuel'' qui récusent l’idée d’un modèle justificatoire unique et universel. ===== Le fondationnalisme mitigé : une articulation entre croyances de base et cohérence ===== Une première famille d’approches hybrides est regroupée sous le nom de ''fondationnalisme mitigé'' ou ''modéré''. Elle part du diagnostic suivant : le fondationnalisme classique, tel qu’on l’a parfois compris, pose des exigences irréalistes à l’égard des croyances de base (infaillibilité, transparence totale, auto-justification forte), tandis que le cohérentisme, s’il est pris de manière « pure », tend à détacher la justification du contact effectif avec la réalité et des sources non doxastiques de nos croyances (perception, mémoire, témoignage, etc.). Le fondationnalisme mitigé cherche à conserver ce qu’il y a de juste dans ces deux intuitions opposées. D’un côté, il maintient que certaines croyances occupent un rôle épistémique privilégié : elles tirent une partie essentielle de leur justification du fait qu’elles sont issues de sources fiables, non elles-mêmes des croyances (expérience sensible, introspection élémentaire, souvenirs ordinaires, etc.), et n’exigent pas toujours de raisons supplémentaires pour être légitimement tenues. De l’autre, il reconnaît que la cohérence globale du système de croyances apporte un surcroît de justification : plus une croyance s’insère dans un réseau harmonieux, explicatif et stable, plus sa prétention à être acceptée se renforce. Dans cette perspective, les croyances de base ne sont ni infaillibles, ni entièrement indépendantes du reste du système ; elles peuvent être révisées si elles entrent en conflit avec un ensemble cohérent mieux étayé. Réciproquement, la cohérence, si importante soit-elle, ne suffit pas toute seule à produire la justification : elle doit s’appuyer sur des points d’ancrage dans des sources cognitives effectivement reliées au monde. Le fondationnalisme mitigé exprime ainsi l’idée que la justification épistémique est le résultat d’une double exigence : enracinement dans des sources appropriées et intégration dans une structure de croyances globalement cohérente. ===== La théorie des vertus épistémiques : un déplacement du centre de gravité ===== La ''théorie des vertus épistémiques'' opère un changement de perspective plus profond encore. Au lieu de se demander d’abord comment des croyances, considérées isolément, sont justifiées par d’autres croyances, elle se demande ce qui caractérise un ''bon sujet connaissant''. La question centrale devient : quelles dispositions intellectuelles, quelles habitudes cognitives excellentes conduisent, de manière fiable, à la formation de croyances vraies et sensées ? Dans cette approche, une croyance est justifiée lorsqu’elle est le produit de l’exercice adéquat d’une ''vertu épistémique'' : par exemple une perception attentive et discriminante, une mémoire entraînée, une capacité d’introspection honnête, un sens critique développé, un goût pour la recherche de contre-exemples, la patience dans l’examen des arguments, ou encore le courage intellectuel de remettre en cause ses propres présupposés. Ce ne sont plus seulement les relations logiques entre propositions qui comptent, mais la manière dont un agent, doté de certaines qualités, mène sa pratique cognitive. Cette réorientation permet de relativiser le conflit entre fondationnalisme et cohérentisme. Une même vertu — par exemple la rigueur dans le raisonnement — peut conduire à exiger, dans certains contextes, des raisons supplémentaires pour des croyances de base apparentes, ou à exiger, dans d’autres, une meilleure cohérence globale du système de croyances. La structure justificatoire apparaît alors comme un effet dérivé de pratiques intellectuelles vertueuses, plutôt que comme un schéma abstrait imposé de l’extérieur. L’enjeu n’est plus seulement de dessiner une architecture formelle, mais de comprendre comment des sujets, socialement situés et historiquement déterminés, développent des dispositions à la fois critiques et confiantes qui les rendent capables de connaître. ===== Le pragmatisme épistémologique : justification, action et expérience ===== Le ''pragmatisme épistémologique'' propose, de son côté, une critique de l’idée même de justification conçue comme structure purement formelle de liens entre croyances. Pour les pragmatistes, une croyance ne se justifie pas d’abord par son insertion dans un système plus ou moins abstrait, mais par la manière dont elle intervient dans l’action, oriente les conduites, et se trouve éprouvée dans l’expérience. La question « Suis-je justifié à croire p ? » se comprend alors à partir de : « Que se passe-t-il si j’agis comme si p était vrai ? Quelles habitudes d’action cette croyance soutient-elle, et se révèlent-elles efficaces, intelligibles, fécondes ? » La justification devient ainsi un moment d’un ''processus d’enquête'' continu : on forme des hypothèses, on agit en conséquence, on observe les résultats, on corrige ou on abandonne certaines croyances, on en renforce d’autres. Une croyance qui résiste à ces épreuves, qui permet d’anticiper avec succès, de résoudre des problèmes réels, de stabiliser l’action collective, acquiert un statut justificatoire renforcé. À l’inverse, une croyance qui entraîne systématiquement des échecs, des blocages pratiques, des contradictions internes dans l’expérience doit être révisée. Ce cadre pragmatiste ne nie pas l’importance des relations logiques entre croyances, mais il les resitue dans une dynamique plus large : celle d’une pratique historique, sociale, traversée par des intérêts, des conflits, des rapports de force. La justification n’est plus une propriété « statique » de croyances contemplées de l’extérieur, mais un moment d’un mouvement par lequel une communauté d’enquêteurs tente de s’orienter dans le monde à partir de ses propres expériences collectives. ===== Épistémologie féministe et épistémologie sociale : la dimension collective et politique de la justification ===== L’'''épistémologie féministe''' et l’'''épistémologie sociale''' introduisent une autre rupture importante avec les schémas classiques. Elles reprochent à la plupart des théories traditionnelles — y compris certaines formes de fondationnalisme, de cohérentisme ou même de théorie des vertus — de privilégier une image abstraite du sujet connaissant : individu neutre, sans corps, sans histoire, sans appartenance de genre, de classe ou de « race ». Or, dans les pratiques réelles de production des savoirs, les sujets sont toujours situés dans des rapports sociaux concrets, marqués par des asymétries de pouvoir, des hiérarchies institutionnelles et des mécanismes d’exclusion. Du point de vue féministe, ces rapports de pouvoir ne constituent pas simplement un décor extérieur à la connaissance ; ils affectent directement ce qui est considéré comme ''preuve'', ce qui est jugé ''pertinent'', qui est entendu ou au contraire disqualifié d’emblée. Des groupes dominés (femmes, classes populaires, minorités racisées, etc.) voient souvent leurs expériences et leurs témoignages moins pris au sérieux, voire déformés, tandis que les groupes dominants bénéficient d’un ''crédit épistémique'' quasi automatique. Les questions de justification ne peuvent donc pas être séparées de l’analyse des injustices épistémiques : refus de croire certains témoins, invisibilisation de certains types d’expériences, appropriation des découvertes d’autres groupes, etc. L’'''épistémologie sociale''' élargit ce constat en soulignant que la connaissance est produite au sein de communautés épistémiques organisées : laboratoires, institutions, réseaux de recherche, médias, espaces militants. Les normes de preuve, les critères de crédibilité, les hiérarchies d’autorité y sont socialement construits et contestés. La justification d’une croyance dépend alors aussi de la manière dont elle circule, est évaluée, corrigée ou verrouillée dans ces collectifs. Une théorie de la justification qui ignore ces dimensions collectives et politiques reste aveugle à une partie décisive de ce qui, en pratique, fait qu’une croyance est effectivement tenue pour légitime ou délégitimée. ===== Le ''foundhérentisme'' : une synthèse explicite entre fondationnalisme et cohérentisme ===== Une tentative de synthèse plus directement systématique entre fondationnalisme et cohérentisme est proposée par ce que Susan Haack a nommé le ''foundherentism'', souvent traduit en français par ''foundhérentisme''. L’idée de base est de refuser l’alternative exclusive entre croyances de base d’un côté et cohérence globale de l’autre, en montrant que la justification réelle repose toujours, en pratique, sur une combinaison des deux. Dans cette perspective, certaines croyances possèdent bien un poids justificatoire particulier en vertu de leur origine dans des sources fiables (perception, mémoire, témoignage compétent, etc.), mais ce poids n’est jamais totalement indépendant de la manière dont ces croyances s’insèrent dans un ensemble plus vaste. Une croyance issue d’une source en général fiable perd une partie de sa force si elle s’accorde mal avec tout un ensemble de données indépendantes solides ; inversement, une croyance bien intégrée dans un réseau cohérent et explicatif peut gagner en crédibilité, même si son origine n’est pas, prise isolément, parfaite. Le ''foundhérentisme'' insiste ainsi sur la nature ''conjuguée'' de la justification : nous faisons confiance à certaines sources en partie parce que leurs livraisons s’accordent, à long terme, avec d’autres sources et d’autres croyances ; et nous faisons confiance à certains schèmes cohérents en partie parce qu’ils s’appuient sur des interactions constantes avec le monde. La justification apparaît alors comme un entrelacement de soutiens « verticaux » (depuis les sources vers les croyances) et de soutiens « horizontaux » (entre croyances), plutôt que comme une édifice strictement hiérarchique ou comme un simple réseau auto-référentiel. ===== Variantes mixtes et infinitisme cohérent : combiner régression, cohérence et ancrage ===== D’autres approches, plus expérimentales, cherchent à intégrer des éléments infinitistes dans un cadre globalement cohérentiste ou pluraliste. L’idée est de reconnaître qu’il est parfois légitime d’exiger que certaines croyances puissent, si besoin, être soutenues par des chaînes de raisons potentiellement très longues, voire illimitées, tout en maintenant que ce travail d’extension des raisons se fait toujours à l’intérieur d’un système de croyances qui doit rester globalement cohérent et connecté au monde. Dans ce type de modèles, l’infinitisme ne vaut plus comme théorie unique et exclusive de la structure de la justification, mais comme une exigence à activer dans certains contextes : lorsque des croyances sont sérieusement contestées, lorsque des enjeux pratiques importants sont en jeu, ou lorsque des désaccords théoriques profonds apparaissent. La cohérence joue alors un rôle de filtrage : toutes les chaînes de raisons ne se valent pas, et seules celles qui s’intègrent dans un système relativement stable, explicatif et sensible aux données empiriques peuvent prétendre à une véritable force justificatoire. De telles conceptions hybrides montrent que l’on peut reprendre des éléments de l’infinitisme — en particulier l’idée d’une amélioration indéfinie possible de la justification — sans pour autant s’engager dans l’image d’agents devant, en permanence, « posséder » des chaînes de raisons effectivement infinies pour chacune de leurs croyances ordinaires. ===== Le pluralisme justificatoire contextuel : rompre avec le modèle unique ===== Enfin, plusieurs auteurs défendent des formes de ''pluralisme justificatoire contextuel''. Selon cette orientation, il est vain de chercher une structure de justification unique et universelle qui s’appliquerait indifféremment à toutes les croyances, dans tous les contextes et pour tous les types de questions. Les exigences justificatoires varient en fonction des buts poursuivis, des risques encourus, de la nature des objets étudiés, des pratiques sociales dans lesquelles les croyances s’insèrent. Ainsi, dans la vie courante, certaines croyances perceptuelles immédiates peuvent être considérées comme suffisamment justifiées par une expérience claire et non trompeuse, sans qu’il soit raisonnable d’exiger une longue chaîne de raisons supplémentaires. Dans la recherche scientifique, en revanche, la justification fera davantage appel à la cohérence globale d’une théorie, à sa capacité explicative, à la convergence de multiples sources de données. Dans un contexte de controverse politique ou morale, ce seront davantage la prise en compte des points de vue marginalisés, l’examen des intérêts en jeu et la critique des rapports de domination qui deviendront centraux. Le pluralisme contextuel ne se contente donc pas de juxtaposer des modèles ; il soutient que la notion même de justification est, en un sens, ''polymorphe''. Elle conserve un noyau commun – l’idée d’une exigence de raisons répondant à une demande de légitimation – mais se déploie différemment selon les pratiques sociales, les disciplines et les enjeux. ===== Conclusion : un paysage épistémologique enrichi et profondément transformé ===== Le développement des approches hybrides et alternatives a profondément modifié le visage de l’épistémologie contemporaine. Là où l’on opposait naguère, de manière souvent exclusive, fondationnalisme, cohérentisme et infinitisme, on reconnaît désormais plus volontiers que chacune de ces positions met en lumière un aspect réel et important de la justification, mais aussi que chacune ne peut prétendre, à elle seule, épuiser la richesse des pratiques de connaissance. Les théories des vertus, les cadres pragmatistes, les épistémologies féministes et sociales, les synthèses de type ''foundhérentiste'' et les pluralismes contextuels déplacent la question elle-même. Plutôt que de chercher obstinément ''la'' structure unique de la justification, elles s’attachent à comprendre comment des agents situés, engagés dans des pratiques sociales, confrontés à des rapports de pouvoir et à des enjeux matériels, parviennent à élaborer des croyances plus ou moins légitimes, plus ou moins stables, plus ou moins ouvertes à la critique. Ce déplacement ne rend pas caducs les débats classiques ; il les réinscrit dans un cadre plus large, où la structure de la justification n’est plus conçue comme un schéma abstrait flottant au-dessus des pratiques, mais comme l’un des aspects d’un ensemble mouvant de formes de vie, de rapports sociaux et de techniques d’enquête. De ce point de vue, les approches hybrides et alternatives ne se contentent pas d’ajouter quelques nuances à un tableau déjà fixé : elles invitent à repenser en profondeur ce que l’on attend d’une théorie de la justification, et à accepter que les exigences de la raison prennent des formes diverses dans des mondes sociaux eux-mêmes traversés par la conflictualité, la domination et la possibilité de leur critique. == Deuxième partie : Sources et méthodes de la connaissance == === Chapitre 4 : La perception === ==== 4.1 Épistémologie de la perception : le fondement empirique de la connaissance ==== ===== Introduction : la perception comme source centrale de justification épistémique ===== La perception constitue, depuis l’Antiquité, une source centrale et décisive de justification épistémique pour nos croyances portant sur le monde externe. À la base de toute connaissance empirique se trouvent nos expériences perceptuelles : ce que nous voyons, entendons, touchons, sentons et goûtons. ''L’épistémologie de la perception'' s’interroge sur la manière dont ces expériences sensorielles peuvent justifier nos croyances concernant les objets et les propriétés du monde extérieur, et sur la structure logique que revêt cette justification perceptuelle. Cette apparente évidence cache toutefois des difficultés conceptuelles profondes. Comment, précisément, la perception nous met-elle en rapport cognitif avec une réalité supposée indépendante de l’esprit ? Qu’est-ce qui confère à nos expériences perceptuelles leur force justificatrice ? La perception nous donne-t-elle un accès ''direct'' aux objets du monde ou seulement un accès ''indirect'', médiatisé par des représentations mentales ? Ces questions structurent l’ensemble du champ de l’épistémologie de la perception et renvoient à un problème plus général : comment pouvons-nous, à partir d’états mentaux, prétendre connaître un monde extérieur à ces états ? ===== Le problème central de l’épistémologie de la perception : le scepticisme à l’égard du monde externe ===== '''L’énoncé du problème de base''' Le problème central de l’épistémologie de la perception peut être formulé ainsi : ''comment la perception peut-elle nous fournir une connaissance, ou au moins une justification, portant sur le monde externe, c’est-à-dire sur des objets et des propriétés situés en dehors de notre esprit ?'' Le point de départ, en apparence banal mais philosophiquement perturbant, est le suivant : nos expériences perceptuelles sont des états mentaux. Voir un arbre, entendre une mélodie, sentir une odeur, ce sont là des événements qui se passent dans notre vie mentale. Dès lors, une distinction s’impose entre l’''expérience perceptuelle'' (un état ou un événement mental) et l’''objet externe'' (supposé exister indépendamment de notre esprit). C’est ce décalage qui semble ouvrir un « gouffre épistémique » : comment passer, sans saut illégitime, de la seule connaissance de nos états mentaux à une justification concernant la réalité objective ? '''L’argument sceptique standard''' L’argument sceptique classique, qui donne sa force à cette inquiétude, peut être schématiquement reconstruit en trois étapes. Tout d’abord, on adopte ce que l’on peut appeler un ''principe d’indirectité'' : nous n’aurions jamais, à strictement parler, un accès immédiat aux objets externes eux-mêmes, mais seulement à nos expériences ou à des « données sensorielles ». Ensuite, on observe que ces expériences peuvent être ''épistémiquement indiscernables'' dans des situations très différentes : l’expérience que j’ai lorsque je vois une table dans des conditions normales peut être, du point de vue phénoménal, rigoureusement la même que celle que j’aurais si j’étais victime d’une hallucination parfaite ou plongé dans un rêve particulièrement vif. Enfin, on en conclut que, si l’on ne peut pas, sur la base de l’expérience seule, distinguer les cas normaux des cas pathologiques, nous n’avons alors aucune ''bonne raison'' décisive de tenir nos perceptions ordinaires pour véridiques plutôt que pour illusoires. L’argument sceptique ne prétend pas prouver que toutes nos perceptions sont fausses, mais qu’il nous manque, pour chacune d’elles, le type de justification que nous croyons habituellement posséder. Il met ainsi sous tension l’idée spontanée selon laquelle la perception serait le fondement indiscutable de toute connaissance empirique. ===== La distinction métaphysique fondamentale : réalisme direct et réalisme indirect ===== '''Le réalisme direct (ou réalisme naïf) : la perception immédiate des objets externes''' Le ''réalisme direct'' — parfois qualifié de ''réalisme naïf'' dans sa version la plus intuitive — soutient que, dans la perception ordinaire, nous sommes directement en contact avec les objets physiques du monde. Lorsque vous voyez une table rouge devant vous, ce que vous percevez, selon ce point de vue, n’est pas une image mentale, ni un « écran de données sensorielles », mais ''la table elle-même'', dans sa matérialité et avec ses propriétés réelles. Ce réalisme direct attribue aux objets externes les propriétés sensibles mêmes que nous leur reconnaissons dans l’expérience courante : la couleur, la forme, la texture, la spatialité seraient véritablement dans les choses telles qu’elles nous apparaissent. L’expérience perceptuelle, loin de nous enfermer dans un monde intérieur de représentations, est alors comprise comme un mode d’ouverture immédiate au monde. L’attrait principal de cette conception tient à son accord étroit avec notre attitude pré-théorique. Dans la vie quotidienne, nous ne nous concevons pas comme des spectateurs d’images internes, mais comme des êtres engagés dans un environnement peuplé d’objets, que nous voyons, touchons, manipulons. Le réalisme direct prend cette phénoménologie au sérieux et revendique son évidence. '''Le réalisme indirect (ou représentationalisme) : la médiation des représentations mentales''' Le ''réalisme indirect'', ou ''réalisme représentationnel'', propose une ontologie plus complexe. Il admet l’existence d’objets externes, mais soutient que ce ne sont pas ces objets eux-mêmes qui sont les ''objets immédiats'' de la perception. Lorsque vous percevez une table rouge, ce que vous appréhendez directement, selon cette conception, est une ''représentation mentale'' ou une ''donnée sensorielle'' qui possède les qualités de « tablité » et de rougeur. L’objet physique n’est alors accessible qu’''indirectement'' : à partir de la structure de cette représentation, vous inférez la présence d’une cause externe adéquate. Ce réalisme indirect fournit un cadre explicatif pour les illusions et les hallucinations. Dans le cas d’une hallucination de table, il n’existe aucun objet externe correspondant, mais il existe bien un état mental qui possède les mêmes qualités phénoménales que dans un cas de perception normale. Ce sont ces états mentaux — et non les objets eux-mêmes — qui sont, à chaque fois, directement présents à l’esprit. La continuité phénoménale entre perception véridique et hallucination s’explique ainsi par le fait que, dans les deux cas, l’objet immédiat est un même type d’état mental. Cependant, cette manière de concevoir la perception rend particulièrement aigu le défi sceptique : si ce à quoi nous avons directement accès n’est jamais l’objet, mais seulement une représentation interne, comment garantir que cette représentation est effectivement causée, de manière fiable, par un monde extérieur plutôt que par des processus cérébraux aberrants ? ===== Le rôle épistémique de l’expérience perceptuelle : simple causalité ou justification proprement dite ? ===== '''La distinction entre lien causal et lien justificatoire''' Une question épistémologique fondamentale consiste à préciser le type de relation qui unit l’expérience perceptuelle et la croyance qui en résulte. Qu’il existe un lien ''causal'' est évident : si je vois un mur, cette expérience visuelle cause habituellement en moi la croyance « il y a un mur devant moi ». Mais la question épistémique est différente : l’expérience ne se contente-t-elle que de ''causer'' la croyance, ou fournit-elle également une ''raison'' pour la tenir pour vraie ? Le fait qu’un état mental en produise un autre n’implique pas, en lui-même, que le second soit justifié par le premier. On peut imaginer des cas où une expérience cause une croyance sans la justifier (par exemple une hallucination provoquée par une drogue), et, inversement, des cas où une expérience contribue à justifier une croyance précisément parce qu’elle est reliée de manière appropriée à la réalité. Toute épistémologie de la perception doit ainsi distinguer soigneusement la ''dimension causale'' (comment les croyances se forment) et la ''dimension normative'' (dans quelles conditions ces croyances sont justifiées). '''L’expérience perceptuelle comme source de justification immédiate''' Une position largement répandue dans la philosophie contemporaine de la perception consiste à soutenir que l’expérience perceptuelle fournit une ''justification immédiate'' à certaines croyances. Lorsque j’ai une expérience visuelle claire d’un objet rouge, il semble qu’''en vertu même'' de cette expérience, j’aie déjà une raison prima facie de croire qu’il y a quelque chose de rouge devant moi. Cette justification est dite « immédiate » en ce sens qu’elle ne dépend pas d’un ensemble préalable de croyances servant de médiation explicite. Cette idée a été théorisée, notamment, sous les étiquettes de ''conservatisme phénoménal'' ou de ''dogmatisme perceptif''. Selon ces approches, le simple fait qu’il ''me semble'' qu’il y a un arbre devant moi suffit, jusqu’à preuve du contraire, à me donner le droit épistémique de croire qu’il y a un arbre. Ce droit peut bien sûr être retiré si l’on découvre des raisons de douter (éclairage trompeur, contexte pathologique, antécédents de hallucinations, etc.), mais il n’est pas nécessaire, pour qu’il existe, de disposer, dès le départ, d’un argument indépendant montrant que nos sens sont globalement fiables. ===== Internalisme et externalisme dans l’épistémologie de la perception ===== '''L’internalisme : tout se joue dans le caractère phénoménal''' L’''internalisme'' en épistémologie soutient que la justification d’une croyance dépend exclusivement de ce qui est, en un sens pertinent, ''interne'' au sujet : ses expériences, ses états réflexifs, ce qui est accessible à l’introspection. Appliqué à la perception, l’internalisme affirme que le statut justificatoire d’une croyance perceptuelle ne dépend que du ''caractère phénoménal'' de l’expérience correspondante, c’est-à-dire de la manière dont elle se présente au sujet. Deux expériences ayant exactement le même profil phénoménal — la même impression de couleur, de forme, de profondeur, de mouvement — doivent, du point de vue internaliste, conférer le même degré de justification, même si l’une est causée par un objet réel et l’autre par une stimulation cérébrale artificielle. L’épistémologie se concentre alors sur ce qui est ''subjectivement'' donné, indépendamment des circonstances causales extérieures. '''L’externalisme : la prise en compte de faits externes à l’expérience''' L’''externalisme'' soutient au contraire que la justification d’une croyance dépend aussi de faits qui ne sont pas reflétés dans le seul vécu phénoménal du sujet. En matière de perception, cela signifie que la fiabilité des processus sensoriels, la relation causale qui relie l’objet externe à l’expérience, ou encore l’inscription de l’agent dans un environnement adéquat jouent un rôle constitutif dans la justification. Ainsi, deux expériences phénoménalement indiscernables peuvent, pour un externaliste, ne pas conférer le même degré de justification. Si dans un monde « normal » votre expérience de voir une table est causée de façon régulière et adéquate par l’objet lui-même, alors cette expérience justifie fortement la croyance « il y a une table ». Si, dans un autre monde, structurée de façon identique du point de vue phénoménal, la même expérience est systématiquement produite par une machine qui vous trompe, la croyance n’est plus, au sens strict, justifiée — même si le sujet n’a aucun moyen interne de faire la différence. L’opposition internalisme/externalisme engage ainsi deux conceptions très différentes de la justification perceptuelle : l’une centrée sur l’accessibilité réflexive, l’autre sur la relation effective au monde. ===== Le contenu perceptuel : propositionnel ou non conceptuel ? ===== '''Le débat sur le contenu de l’expérience perceptuelle''' Une autre controverse importante porte sur la nature du ''contenu'' de l’expérience perceptuelle. Les expériences perceptuelles ont-elles un contenu ''propositionnel'' — du type : « il y a un arbre vert à tel endroit » — qui peut être évalué comme vrai ou faux ? Ou bien possèdent-elles seulement une structure phénoménale, riche mais non articulée conceptuellement, que nous ne transformons en propositions que dans un second temps, par un travail interprétatif ? Si l’on soutient que les expériences ont un contenu propositionnel, il devient relativement simple de concevoir comment elles justifient des croyances : elles présentent le monde comme étant d’une certaine façon, et la croyance reprend sous forme jugée ce que l’expérience donnait déjà sous forme perceptive. L’écart entre expérience et croyance se réduit, dans ce cas, à une différence de « format ». Si, au contraire, l’on soutient que les expériences ne possèdent pas, en elles-mêmes, de contenu propositionnel — qu’elles fournissent un « matériau sensible » sans structure conceptuelle — alors il faut expliquer comment un tel matériau peut néanmoins jouer un rôle justificatoire. Il faut, en particulier, rendre compte de la manière dont la simple présence de qualités sensibles (couleurs, formes, textures) peut fonder rationnellement une croyance articulée. '''L’exigence davidsonienne et la réponse non conceptualiste''' Donald Davidson a défendu l’idée qu’''un état ne peut justifier une croyance que s’il possède lui-même un contenu susceptible d’être vrai ou faux''. Dans cette perspective, les expériences purement phénoménales, dépourvues de toute forme de contenu conceptuel, ne pourraient pas, à proprement parler, servir de raisons : elles pourraient, au mieux, ''causer'' des croyances, mais non les ''fonder'' rationnellement. D’où l’idée que le contenu perceptuel doit être, en un certain sens, propositionnel. Les ''non conceptualistes'' contestent cette exigence. Ils soutiennent que l’on peut avoir des raisons qui ne sont pas encore formulées sous forme de propositions, mais qui se présentent sous la forme de ''présentations'' sensibles riches, suffisamment structurées pour guider la croyance et l’action. Selon cette approche, l’expérience perceptuelle joue un rôle justificatoire sans qu’il soit nécessaire de lui attribuer d’emblée la forme d’un jugement : c’est parce que le monde nous apparaît d’une certaine façon, avant toute verbalisation, que certaines croyances se trouvent plus « naturelles », plus aisées à adopter, et d’autres moins. ===== Le phénomène de la pénétrabilité cognitive : l’influence des états mentaux sur la perception ===== '''La question de la pénétrabilité cognitive''' Une dimension de plus en plus étudiée concerne la ''pénétrabilité cognitive'' de la perception : dans quelle mesure nos croyances, nos désirs, nos attentes, nos catégories conceptuelles peuvent-ils modifier le contenu ou même le caractère phénoménal de l’expérience perceptuelle ? On peut, par exemple, se demander si un historien de l’art et un passant peu averti voient vraiment ''la même'' peinture. Le premier discerne des traits de style, des références historiques, des détails compositionnels auxquels le second reste largement insensible. Faut-il dire qu’ils perçoivent différemment l’œuvre elle-même, ou bien qu’ils ont la même perception mais des ''interprétations'' différentes ? De même, des préjugés racistes ou sexistes peuvent-ils influer sur ce que l’on croit voir dans une situation donnée (par exemple, la perception d’un geste comme menaçant ou non) ? '''Les implications épistémiques''' Si la perception est cognitivement pénétrable, alors le statut justificatoire de nos expériences perceptuelles dépendra, au moins en partie, de l’arrière-plan de croyances qui les façonne. Des croyances fausses ou biaisées peuvent « contaminer » l’expérience, la rendre trompeuse ou moins fiable ; des croyances vraies, au contraire, peuvent affiner la perception, la rendre plus discriminante et plus apte à saisir les traits pertinents de la réalité. Cela complique considérablement l’idée d’une « base perceptive neutre » sur laquelle viendraient ensuite se greffer des interprétations. L’épistémologie de la perception doit alors tenir compte du fait que le regard lui-même est historiquement et socialement formé, et que la perception n’est pas seulement un afflux passif de données, mais déjà une manière, située, de prendre position dans le monde. ===== Conclusion : l’enjeu permanent de l’épistémologie de la perception ===== L’épistémologie de la perception demeure au cœur de la réflexion épistémologique contemporaine, parce qu’elle engage à la fois la question du ''contact'' avec le monde et celle de la ''légitimité'' de nos croyances empiriques. Les interrogations relatives à la manière dont la perception peut justifier la formation de croyances sur le monde externe, à la structure de cette justification (immédiate ou médiatisée, interne ou externe), au statut du contenu perceptuel (propositionnel ou non conceptuel), ainsi qu’au degré de pénétrabilité cognitive de l’expérience, restent l’objet de débats intenses et nourris. Loin de se réduire à des disputes techniques, ces débats mettent en lumière des options philosophiques profondes : doit-on privilégier la transparence apparente de l’expérience ordinaire ou la force des arguments sceptiques ? Faut-il penser la justification à partir de l’agent et de ses vertus, à partir de la structure de ses croyances, ou à partir des relations causales qui le rattachent au monde ? En ce sens, l’épistémologie de la perception n’est pas un chapitre spécialisé de la théorie de la connaissance, mais un lieu stratégique où se rejouent, de manière concentrée, les grandes tensions de la philosophie : entre subjectivité et objectivité, entre vécu et science, entre confiance et doute. ==== 4.2 Théories de la perception : les grandes approches philosophiques ==== ===== Introduction : le problème fondamental de la perception ===== La perception constitue notre lien premier et le plus immédiat avec le monde extérieur, et pourtant elle présente une énigme philosophique profonde. Comment des expériences sensorielles, qui semblent se dérouler « en nous », peuvent-elles nous donner accès à une réalité extérieure et indépendante de l’esprit ? Que percevons-nous véritablement : les objets eux-mêmes, ou seulement des représentations mentales qui en seraient les images ? L’expérience perceptive nous met-elle en rapport direct avec la réalité, ou interpose-t-elle entre nous et elle un écran de phénomènes psychiques dont nous ne pouvons sortir ? Ces interrogations, loin d’être de simples curiosités théoriques, structurent l’ensemble de la philosophie de la perception. Elles engagent à la fois des enjeux ontologiques (qu’est-ce qu’un objet perçu ?), épistémologiques (comment la perception peut-elle fonder la connaissance ?) et phénoménologiques (quel est le mode d’apparaître propre au perçu ?). Plusieurs grandes familles de théories se sont développées pour y répondre, chacune proposant une conception spécifique de la nature, de la structure et du statut ontologique de l’expérience perceptuelle. ===== Le réalisme direct : l’accès immédiat aux objets externes ===== '''La thèse fondamentale du réalisme direct''' Le '''réalisme direct''' (souvent appelé, dans sa version la plus spontanée, ''réalisme naïf'') soutient que les objets immédiats de notre perception sont les objets matériels eux-mêmes, existant indépendamment de notre esprit. Lorsque vous voyez une table rouge devant vous, ce que vous percevez, selon cette conception, n’est pas une image mentale de la table, mais la table elle-même, avec ses propriétés réelles (sa couleur, sa forme, sa texture, sa position dans l’espace). Le réalisme direct affirme ainsi que la perception établit une relation cognitive immédiate entre le sujet et l’objet : il n’existe, en droit, aucun intermédiaire ontologiquement distinct – pas de « chose mentale », pas de « donnée sensible » autonome – qui se placerait entre l’esprit percevant et le monde. La perception est un mode de présence directe de l’objet à la conscience. '''L’attrait et la force intuitive du réalisme direct''' Cette position bénéficie d’un puissant soutien intuitif. Dans le langage ordinaire, lorsque l’on demande à quelqu’un ce qu’il a perçu, il répond : « une table », « un bruit de pas », « un parfum de fleur », et non « une représentation interne de table » ou « une donnée sensorielle de rougeur ». Le réalisme direct semble prendre au sérieux cette évidence pré-philosophique : en percevant, nous sommes d’emblée dehors, dans le monde. De plus, le réalisme direct paraît rendre compte sans détours de la fonction cognitive de la perception : si nous percevons directement les objets et leurs propriétés, alors la perception s’impose comme une source de connaissance authentique et relativement sûre du monde extérieur. Il n’y a pas, du moins en première analyse, de « voile » interposé entre nous et les choses. '''Les difficultés du réalisme direct : variation, illusion et hallucination''' Toutefois, le réalisme direct se heurte à des difficultés classiques. L’argument de la '''variation perceptuelle''' montre que la même réalité matérielle peut donner lieu à des expériences très différentes. Un bâton partiellement plongé dans l’eau nous apparaît courbé, alors qu’il est effectivement droit ; un objet semble changer de couleur selon l’éclairage ou l’angle de vue. Deux sujets, ou même le même sujet à des moments distincts, peuvent avoir des vécus perceptifs divergents alors que l’objet externe demeure identique. Comment comprendre, dans le cadre d’un réalisme direct strict, qu’un seul et même objet puisse correspondre à une pluralité d’expériences discordantes, sans introduire quelque chose comme un « mode d’apparition » ou une « manière pour l’objet de se manifester », qui n’est déjà plus l’objet lui-même ? Plus radical encore est le problème des '''hallucinations'''. Il est concevable – et cliniquement attesté – qu’un individu vive une expérience perceptive phénoménalement indiscernable d’une perception authentique (par exemple « voir » une table rouge, avec la même vivacité et la même richesse de détails) alors qu’il n’y a, en réalité, aucune table. Si, dans les deux cas, l’expérience subjective est exactement la même, comment soutenir que, dans un cas, le sujet est en contact direct avec un objet réel et, dans l’autre, n’a affaire qu’à un « rien » ? Il semble, au minimum, qu’il faille introduire un élément commun aux deux situations, qui ne peut être l’objet externe puisqu’il fait défaut dans l’hallucination. C’est ce point que le réalisme direct doit clarifier. ===== Le réalisme indirect : la théorie des données sensorielles ===== '''Les données sensorielles comme objets immédiats de perception''' Pour répondre à ces difficultés, le '''réalisme indirect''' – encore appelé ''réalisme représentationnel'' ou ''théorie des données sensorielles'' – propose une autre analyse. Selon cette approche, ce que nous percevons immédiatement ne sont pas les objets matériels, mais des entités mentales dépendantes de l’esprit, souvent nommées « données sensibles » ou « sense-data ». Les objets physiques ne seraient perçus que de manière médiate, à travers ces données sensorielles qui les représentent. Ainsi, lorsque je regarde une rose rouge, l’objet immédiat de ma perception serait une certaine qualité sensible de rougeur, présente dans mon expérience, et non la rose matérielle elle-même. C’est en vertu de cette donnée sensible – de la manière dont elle se donne à moi – que je suis fondé à inférer l’existence d’un objet externe qui en serait la cause ou le support. '''Illusion et hallucination : la ressource explicative du réalisme indirect''' Cette théorie semble mieux armée que le réalisme direct pour rendre compte des illusions et des hallucinations. Dans le cas du bâton plongé dans l’eau, elle peut affirmer que l’expérience est correcte quant à ce qu’elle donne immédiatement : la donnée sensible présente dans la conscience a effectivement une forme apparente courbe. L’erreur ne porte pas sur l’expérience elle-même, mais sur le jugement qui en infère que l’objet externe est courbé. De même, une hallucination peut être, sur le plan phénoménal, strictement identique à une perception véridique, parce qu’elle met en jeu une donnée sensible de même type – la même qualité de rouge, la même configuration phénoménale – sans qu’il y ait, dans un cas, d’objet externe correspondant. On comprend alors comment deux expériences subjectivement indiscernables peuvent se distinguer quant à leur relation à la réalité. '''Le « voile de la perception » et les difficultés ontologiques''' Mais le réalisme indirect soulève à son tour des inquiétudes majeures. Si nous ne sommes directement en contact qu’avec des données sensorielles internes, comment pouvons-nous jamais savoir si elles correspondent à des objets extérieurs ? Nous semblons enfermés derrière un ''voile de la perception'' : tout ce à quoi nous avons accès est constitué par des contenus mentaux, dont nous ne pouvons comparer la « fidélité » avec aucune réalité indépendante. La voie du scepticisme sur l’existence ou sur la nature du monde externe paraît ainsi largement ouverte. S’y ajoute un problème ontologique : les données sensorielles sont typiquement décrites comme non physiques, non spatiales, inextensives, tandis que les objets matériels sont étendus, situés, composés de parties. Comment des entités aussi différentes pourraient-elles « représenter » adéquatement les objets physiques ? Comment une simple qualité de rougeur mentale pourrait-elle être adéquatement reliée à des propriétés physiques de réflexion de la lumière, de structure microscopique, etc. ? Le réalisme indirect doit proposer un pont explicatif entre ces deux ordres d’être. ===== Le représentationalisme : la perception comme représentation du monde ===== '''Le contenu représentationnel comme essence de l’expérience perceptive''' Le '''représentationalisme''' entend dépasser l’alternative trop tranchée entre réalisme direct et réalisme indirect. Il soutient que l’essence de l’expérience perceptuelle réside dans son '''contenu représentationnel''' : percevoir, c’est se trouver dans un état mental qui représente le monde comme étant d’une certaine manière. Sur cette conception, l’expérience perceptive n’est pas d’abord une chose (une « donnée ») dont nous serions conscients, mais un acte ou un état qui se rapporte, par sa forme même, à des objets et à des propriétés possibles. Deux expériences sont phénoménalement identiques si, et seulement si, elles présentent au sujet le monde selon le même contenu : si elles représentent les mêmes objets comme possédant les mêmes propriétés dans les mêmes relations. Cela permet de dire qu’une hallucination complète et une perception véridique peuvent partager le même contenu représentationnel : dans les deux cas, le monde est présenté au sujet comme contenant une table rouge à tel endroit. La différence ne porte plus sur le vécu lui-même, mais sur le fait que, dans un cas, ce contenu correspond à un état de choses réel, et, dans l’autre, non. '''Les vertus explicatives du représentationalisme''' Le représentationalisme présente plusieurs avantages. Il sauvegarde, d’une part, l’intuition que, dans la perception, c’est bien le monde que nous visons : nos expériences ne sont pas des objets d’intérêt en elles-mêmes, mais des façons de nous rapporter aux objets et aux événements extérieurs. D’autre part, il rend compte de l’indiscernabilité phénoménale entre certaines hallucinations et certaines perceptions véridiques, en la rattachant à l’identité de contenu : si l’expérience représente le monde de la même manière, elle doit, du point de vue du vécu, « se donner » de la même manière au sujet, que ce contenu soit effectivement réalisé ou non. Enfin, le représentationalisme évite de réifier les « données sensibles » comme des entités mentales autonomes interposées entre nous et le monde. Il n’est pas nécessaire de supposer un « écran » de choses mentales : il suffit de reconnaître que l’expérience a un certain contenu, qui peut être plus ou moins adéquat à ce qu’il y a effectivement. En ce sens, le représentationalisme se rapproche du réalisme direct, tout en conservant une analyse plus fine de la structure de l’expérience. ===== L’approche écologique : la perception comme détection des invariants ===== '''La théorie écologique de James Gibson''' James J. Gibson a proposé, au XX<sup>e</sup> siècle, une ''théorie écologique de la perception'' qui remet en cause les présupposés mêmes des débats traditionnels.<ref>{{Ouvrage | prénom1 = James J. | nom1 = Gibson | titre = The Ecological Approach to Visual Perception | éditeur = Houghton Mifflin | lieu = Boston | année = 1979}}</ref> Selon lui, l’idée d’un « problème de la perception » naît d’une conception trop internaliste et passive de l’expérience : on se représente le sujet comme recevant des « sensations » brutes qu’il faudrait ensuite interpréter, alors qu’en réalité la perception est d’emblée un rapport dynamique entre un organisme et un environnement structuré. Pour Gibson, nous ne percevons pas des « stimulations » ponctuelles sur les récepteurs, mais des '''invariants''' dans le flux sensoriel, invariants qui sont disponibles dans le milieu lorsque l’organisme se déplace, explore, oriente sa tête, ses yeux, son corps. Le ''flux optique'' – l’ensemble des variations structurées de la lumière qui parvient aux yeux d’un sujet en mouvement – contient déjà de l’information sur la profondeur, la texture, la forme, le mouvement des objets. La perception visuelle n’a pas à « reconstruire » le monde à partir de données lacunaires : elle consiste à détecter, dans ce flux richement structuré, les régularités pertinentes. '''Les affordances : les possibilités d’action perçues''' Une notion centrale de la théorie gibsonienne est celle d’'''affordance''', c’est-à-dire la possibilité d’action qu’un élément de l’environnement offre à un organisme donné. Un rocher peut être « escaladable » pour un être humain adulte, mais non pour un jeune enfant ; une surface peut être « franchissable » pour un piéton, mais non pour un véhicule. L’objet perçu n’est alors pas seulement un ensemble de propriétés géométriques et optiques, mais un ensemble de possibilités pratiques : une chaise est immédiatement perçue comme un support pour s’asseoir, un escalier comme quelque chose que l’on peut monter ou descendre. Gibson soutient que ces affordances sont perçues ''directement'' : nous ne calculons pas d’abord des propriétés neutres de l’objet pour en déduire ensuite qu’il permet telle ou telle action ; nous saisissons d’emblée l’objet comme « pouvant être utilisé pour… ». La perception est ainsi inséparable de l’action possible, et la frontière entre perception et motricité devient poreuse. '''Forces et limites de l’approche écologique''' L’approche écologique a le mérite de souligner le caractère actif, orienté vers l’action et profondément contextuel de la perception. Elle rompt avec l’image d’un sujet passivement bombardé de sensations et insiste sur la richesse de l’information disponible dans l’environnement lui-même. Elle prétend par là dissoudre le « problème du voile de la perception » : si l’information écologique est directement accessible, il n’y a pas à « passer » par des entités mentales interposées. Cependant, la théorie gibsonienne rencontre des objections. On peut se demander, d’abord, comment elle rend compte des '''illusions''' : si la perception est une détection directe d’invariants réels, comment expliquer que nous soyons parfois systématiquement induits en erreur (perspective trompeuse, mirages, illusions de contraste, etc.) ? En outre, certains phénomènes – notamment les '''hallucinations''', qui surviennent en l’absence de tout stimulus approprié – résistent à une analyse strictement écologique. Si toute perception suppose un couplage adéquat entre organisme et environnement, que dire de ces expériences où le système nerveux produit, pour ainsi dire, « de lui-même » des contenus perceptifs ? L’approche écologique doit soit minimiser ces phénomènes, soit s’efforcer de les intégrer dans une théorie plus large. ===== L’approche constructiviste : la perception comme inférence inconsciente ===== '''La perception comme hypothèse interprétative''' À l’opposé de la perspective gibsonienne, les théories '''constructivistes''' soutiennent que la perception n’est pas la simple réception d’une information déjà structurée, mais le résultat d’un processus d’''inférence'' à partir de données sensorielles partielles et ambiguës. Inspiré notamment par les travaux de Helmholtz, ce courant affirme que voir, entendre, toucher, c’est « poser des hypothèses » – le plus souvent inconscientes – sur les causes probables de nos stimulations.<ref>{{Ouvrage | prénom1 = Hermann von | nom1 = Helmholtz | titre = Handbuch der physiologischen Optik | éditeur = L. Voss | lieu = Hambourg | année = 1867}}</ref> Le système perceptif reçoit des motifs de stimulation sur les récepteurs sensoriels (rétine, oreille interne, peau, etc.). Ces motifs, pris isolément, sont insuffisants pour déterminer de manière univoque la configuration du monde qui les produit ; il existe une pluralité de « solutions » possibles. La perception consiste alors dans le choix d’une hypothèse interprétative, guidée par l’expérience passée, les régularités apprises, la probabilité des différentes configurations. Ce travail de construction s’opère en deçà de la conscience réflexive : nous n’avons accès qu’au résultat stabilisé – la scène perçue – non au processus inférentiel qui y conduit. '''Le codage prédictif : une élaboration contemporaine''' Une version contemporaine influente de ce constructivisme est la théorie du '''codage prédictif'''. Selon ce modèle, le cerveau fonctionne comme un système génératif qui élabore en permanence des prédictions quant aux entrées sensorielles à venir, à partir de modèles internes du monde. Les signaux ascendants en provenance des récepteurs ne sont pas traités comme des données brutes à interpréter, mais comme des ''erreurs de prédiction'' : des écarts entre ce qui était attendu et ce qui est effectivement reçu.<ref>{{Article | prénom1 = Karl | nom1 = Friston | titre = The free-energy principle: a unified brain theory? | périodique = Nature Reviews Neuroscience | volume = 11 | année = 2010 | pages = 127-138}}</ref> Dans cette perspective, percevoir, c’est continuellement ajuster des modèles hypothétiques pour minimiser l’erreur de prédiction. La perception résulte de l’équilibre entre des influences descendantes (les attentes, les hypothèses, les cadres conceptuels) et des influences ascendantes (les contraintes imposées par le signal sensoriel). Ce schème permet de rendre compte à la fois de la stabilité de la perception (nos modèles anticipent correctement la plupart des situations ordinaires) et de la possibilité de '''hallucinations''' : lorsque les modèles internes deviennent excessivement rigides ou trop fortement pondérés, ils peuvent imposer leur contenu malgré des signaux sensoriels faibles ou contradictoires. Le sujet peut alors « percevoir » des objets ou des événements qui ne sont pas effectivement présents. ===== Conclusion : la pluralité des perspectives théoriques ===== Les grandes théories de la perception – réalisme direct, réalisme indirect, représentationalisme, approche écologique, constructivisme inférentialiste – mettent chacune en lumière un aspect essentiel de l’expérience perceptive : sa prétention à nous mettre en rapport avec un monde indépendant, sa vulnérabilité aux erreurs, son caractère intrinsèquement représentationnel, sa dimension pratique orientée vers l’action, ou encore le rôle des processus de construction et de prédiction. Aucune de ces approches ne s’est imposée comme définitivement victorieuse. Le réalisme direct garde le mérite de prendre au sérieux notre expérience d’un contact immédiat avec les choses, mais doit affronter les cas d’illusion et d’hallucination. Le réalisme indirect explique ces cas au prix d’un éloignement préoccupant du monde externe. Le représentationalisme offre une articulation fine entre contenu phénoménal et contenu intentionnel, mais doit préciser la nature de ce contenu et sa relation au physique. L’approche écologique insiste avec force sur l’inscription corporelle et pratique de la perception, tandis que le constructivisme et le codage prédictif mettent l’accent sur l’activité interprétative et la fonction modélisatrice du cerveau. Il est vraisemblable qu’une théorie satisfaisante de la perception devra combiner, plutôt qu’opposer, plusieurs de ces intuitions : reconnaître à la fois la richesse de l’information environnementale, le rôle des attentes et des modèles internes, la dimension représentationnelle des vécus perceptifs et l’orientation pratique de notre rapport au monde. La perception apparaît alors comme un nœud complexe où se croisent le corps, l’environnement, les structures cognitives et les normes de la connaissance. ==== 4.3 Justification perceptuelle : comment la perception justifie-t-elle nos croyances ? ==== ===== Introduction : le problème de la justification perceptuelle ===== La question centrale de l'épistémologie de la perception ne concerne pas seulement la nature métaphysique de l'expérience perceptuelle, mais aussi et surtout son rôle épistémique : comment nos expériences perceptuelles peuvent-elles justifier nos croyances sur le monde externe ? En quoi consiste précisément la relation de ''justification'' que l'expérience perceptuelle entretient avec les croyances perceptuelles ? Cette interrogation soulève des difficultés conceptuelles profondes. L'expérience perceptuelle elle-même n'est pas une croyance — c'est un état mental distinct possédant un caractère phénoménal et un contenu représentationnel. Comment donc un état mental non doxastique (l'expérience) peut-il fournir une justification pour un état mental doxastique (la croyance) ? Quelle est la structure logique de cette relation justificatoire ? Est-elle immédiate ou médiatisée ? Dépend-elle uniquement de facteurs internes à l'esprit du sujet, ou implique-t-elle également des facteurs externes concernant la fiabilité causale de l'expérience ?<ref>Goldman, A. I. & McGrath, M. (2015). ''Epistemology: A Contemporary Introduction''. Oxford University Press.</ref> ===== Le fondationnalisme perceptuel : la perception comme fondement de la justification ===== '''La thèse fondamentale du fondationnalisme épistémologique''' Le fondationnalisme constitue l'une des deux grandes architectures traditionnelles de la structure de la justification épistémique. Selon cette approche, nos croyances justifiées se divisent en deux catégories ontologiquement et épistémologiquement distinctes : les ''croyances de base'' (ou croyances fondamentales) et les ''croyances dérivées'' (ou croyances non fondamentales).<ref>Audi, R. (2011). ''Epistemology: A Contemporary Introduction to the Theory of Knowledge'', 3e édition. Routledge.</ref> Les croyances de base possèdent une justification qui ne dépend pas d'autres croyances — elles sont ''immédiatement'' justifiées ou ''auto-justifiées''. Les croyances dérivées, par contraste, obtiennent leur justification de manière ''médiatisée'' — par inférence ou par dérivation à partir des croyances de base. Selon le fondationnalisme, cette structure hiérarchique évite la régression infinie de la justification : la chaîne de justifications s'arrête aux croyances de base, qui ne requièrent pas elles-mêmes de justification ultérieure par d'autres croyances.<ref>BonJour, L. (1985). ''The Structure of Empirical Knowledge''. Harvard University Press.</ref> '''Le fondationnalisme perceptuel : les croyances perceptuelles comme croyances de base''' Le ''fondationnalisme perceptuel'' applique cette structure architecturale à la justification des croyances perceptuelles. Selon cette position, les croyances perceptuelles simples et directes — par exemple, la croyance « il y a une table rouge devant moi » formée sur la base d'une expérience visuelle appropriée — constituent des croyances de base. Elles sont immédiatement justifiées par l'expérience perceptuelle correspondante, sans qu'il soit nécessaire de posséder d'autres croyances justificatrices intermédiaires.<ref>Pryor, J. (2000). « The Skeptic and the Dogmatist ». ''Noûs'', 34(4), 517-549.</ref> Cette approche possède un attrait intuitif puissant. Dans l'expérience ordinaire, quand nous percevons une table rouge, nous formons immédiatement et spontanément la croyance qu'une table rouge est présente — nous ne passons pas par un processus inférentiel conscient où nous raisonnons à partir de prémisses concernant notre expérience vers une conclusion sur le monde externe. La justification semble immédiate, directe et non médiatisée. '''Les défis du fondationnalisme perceptuel : le dilemme de Sellars''' Cependant, le fondationnalisme perceptuel rencontre une objection profonde et influente formulée par Wilfrid Sellars dans son essai classique ''Empirisme et philosophie de l'esprit'' (1956) : le ''dilemme du donné'' (''the Myth of the Given''). Sellars soutient que les expériences perceptuelles ne peuvent pas simultanément satisfaire deux exigences apparemment nécessaires pour servir de fondement justificatoire aux croyances.<ref>Sellars, W. (1956). « Empiricism and the Philosophy of Mind », dans Feigl, H. & Scriven, M. (dir.), ''Minnesota Studies in the Philosophy of Science'', vol. I, p. 253-329. University of Minnesota Press.</ref> D'un côté, pour qu'une expérience perceptuelle justifie une croyance, elle doit posséder un ''contenu conceptuel'' ou ''propositionnel'' — elle doit représenter le monde comme étant d'une certaine manière, et ce contenu doit être susceptible d'être vrai ou faux. Car seul un état possédant un contenu évaluable pour sa vérité peut justifier rationnellement une croyance. Cependant, si l'expérience possède un contenu conceptuel, alors elle semble elle-même nécessiter une justification — comment savons-nous que l'expérience représente correctement le monde ?<ref>deVries, W. A. & Triplett, T. (2000). ''Knowledge, Mind, and the Given: Reading Wilfrid Sellars's "Empiricism and the Philosophy of Mind"''. Hackett Publishing.</ref> D'un autre côté, si l'expérience perceptuelle ne possède pas de contenu conceptuel — si elle constitue simplement une « impression brute » ou un « donné » non conceptuel — alors elle ne peut pas justifier rationnellement une croyance, car elle ne se tient pas dans une relation logique appropriée avec la croyance. La justification requiert des relations rationnelles ou logiques, et de telles relations ne peuvent exister qu'entre états possédant un contenu propositionnel.<ref>McDowell, J. (1994). ''Mind and World''. Harvard University Press.</ref> ===== Le conservatisme phénoménal : la phénoménologie comme source de justification ===== '''L'intuition fondamentale du conservatisme phénoménal''' Le ''conservatisme phénoménal'' constitue une position fondationnaliste contemporaine influente défendue notamment par Michael Huemer et James Pryor. Selon cette approche, l'expérience perceptuelle justifie immédiatement les croyances perceptuelles en vertu de son ''caractère phénoménal'' — c'est-à-dire en vertu de la manière dont l'expérience se présente ou apparaît au sujet.<ref>Huemer, M. (2001). ''Skepticism and the Veil of Perception''. Rowman & Littlefield.</ref> Le principe central du conservatisme phénoménal peut s'énoncer ainsi : si quelque chose ''semble'' être le cas pour un sujet S — si S a une expérience selon laquelle P — alors S possède par là même une justification ''prima facie'' pour croire que P, en l'absence de raisons contraires ou de défaiseurs. Cette justification est immédiate : elle ne dépend pas de la possession d'autres croyances justifiées concernant l'expérience ou sa fiabilité.<ref>Huemer, M. (2007). « Compassionate Phenomenal Conservatism ». ''Philosophy and Phenomenological Research'', 74(1), 30-55.</ref> '''La force phénoménale et l'attitude de présentation''' Selon les partisans du conservatisme phénoménal, ce qui distingue l'expérience perceptuelle d'autres états mentaux comme l'imagination ou la simple contemplation intellectuelle est sa ''force phénoménale'' ou son ''attitude de présentation''. Quand vous percevez visuellement une table rouge, l'expérience ne se contente pas de représenter une table rouge — elle ''présente'' cette table comme étant réellement présente, comme étant actualisée ici et maintenant. Elle possède un caractère d'immédiateté et de présence qui distingue phénoménalement la perception de l'imagination.<ref>Tucker, C. (2010). « Why Open-Minded People Should Endorse Dogmatism ». ''Philosophical Perspectives'', 24(1), 529-545.</ref> Cette force phénoménale distinctive, cette manière spécifique dont la perception présente son contenu comme actualisé, est ce qui confère à l'expérience perceptuelle son pouvoir justificatoire unique. L'imagination peut représenter le même contenu — vous pouvez imaginer une table rouge — mais elle ne présente pas ce contenu avec la force d'actualisation qui caractérise la perception. C'est pourquoi l'imagination ne justifie pas les croyances perceptuelles alors que la perception le fait. '''Les objections au conservatisme phénoménal : le problème des apparences trompeuses''' Cependant, le conservatisme phénoménal rencontre des objections sérieuses. Une difficulté majeure concerne les cas où quelque chose « semble » être le cas en raison de processus cognitifs dysfonctionnels ou biaisés. Supposez qu'un sujet, en raison d'un désir intense ou d'une peur pathologique, expérimente une apparence selon laquelle P, alors même qu'aucune évidence perceptuelle authentique ne soutient P. Le conservatisme phénoménal semble impliquer que ce sujet possède une justification ''prima facie'' pour croire P, ce qui paraît contre-intuitif.<ref>Siegel, S. (2012). « Cognitive Penetrability and Perceptual Justification ». ''Noûs'', 46(2), 201-222.</ref> Plus généralement, le conservatisme phénoménal semble trop libéral ou permissif — il confère une justification à trop de croyances. Si toute apparence ou tout « sembler » suffit pour conférer une justification ''prima facie'', alors même les apparences générées par des processus cognitifs peu fiables ou dysfonctionnels confèrent une justification, ce qui semble problématique.<ref>Markie, P. (2005). « The Mystery of Direct Perceptual Justification ». ''Philosophical Studies'', 126(3), 347-373.</ref> ===== Le fiabilisme processuel : la fiabilité causale comme fondement de la justification ===== '''La rupture externaliste : de l'accessibilité interne à la fiabilité objective''' Le ''fiabilisme processuel'', développé principalement par Alvin Goldman, représente une rupture profonde avec les approches traditionnelles internalistes de la justification. Selon le fiabilisme, une croyance est justifiée si et seulement si elle est produite par un ''processus cognitif fiable'' — c'est-à-dire un processus qui produit généralement ou systématiquement des croyances vraies plutôt que fausses.<ref>Goldman, A. I. (1979). « What Is Justified Belief? », dans Pappas, G. S. (dir.), ''Justification and Knowledge'', p. 1-23. Reidel.</ref> Cette approche est ''externaliste'' en ce sens que la justification d'une croyance dépend de facteurs qui peuvent être externes à la perspective consciente du sujet — notamment, de la fiabilité objective du processus cognitif qui a produit la croyance. Un sujet peut posséder une croyance justifiée sans nécessairement savoir ou avoir accès au fait que son processus cognitif est fiable.<ref>Goldman, A. I. & Beddor, B. (2021). « Reliabilist Epistemology ». ''Stanford Encyclopedia of Philosophy'', E. N. Zalta (dir.).</ref> '''Application à la justification perceptuelle''' Appliqué à la justification perceptuelle, le fiabilisme processuel affirme que les croyances perceptuelles sont justifiées si et seulement si elles sont produites par des processus perceptuels fiables. Par exemple, votre croyance qu'une table rouge est devant vous est justifiée si elle résulte d'un processus de perception visuelle qui produit généralement des croyances vraies dans des conditions normales d'observation. Cette approche offre plusieurs avantages théoriques importants. D'abord, elle explique pourquoi la perception constitue généralement une source fiable de justification — parce que nos systèmes perceptuels sont évolutivement adaptés pour produire des représentations véridiques de l'environnement. Deuxièmement, elle rend compte naturellement de la variation contextuelle de la justification perceptuelle — la même expérience peut justifier une croyance dans un contexte mais pas dans un autre, selon la fiabilité du processus dans ce contexte spécifique.<ref>Alston, W. P. (1995). « How to Think About Reliability ». ''Philosophical Topics'', 23(1), 1-29.</ref> '''Le problème de la généralité : quel processus est pertinent ?''' Cependant, le fiabilisme processuel rencontre une difficulté technique majeure connue sous le nom de ''problème de la généralité''. Pour évaluer si une croyance est produite par un processus fiable, nous devons identifier le ''type de processus'' pertinent et évaluer sa fiabilité statistique. Mais toute instance particulière de formation de croyance peut être classée sous de multiples types de processus de généralité variable.<ref>Conee, E. & Feldman, R. (1998). « The Generality Problem for Reliabilism ». ''Philosophical Studies'', 89(1), 1-29.</ref> Par exemple, votre croyance qu'une table rouge est présente pourrait être produite par : (a) le processus très général de « perception visuelle » ; (b) le processus plus spécifique de « perception visuelle dans des conditions d'éclairage normal » ; (c) le processus encore plus spécifique de « perception visuelle d'objets rouges dans des conditions d'éclairage normal par un sujet ayant une vision normale ». Chacun de ces types de processus peut avoir un taux de fiabilité différent, et donc la justification de la croyance variera selon le type choisi. Le problème de la généralité demande : selon quel principe doit-on choisir le type de processus pertinent pour évaluer la justification ? Aucune solution largement acceptée à ce problème n'a encore émergé dans la littérature fiabiliste.<ref>Lyons, J. C. (2019). « Algorithm and Parameters: Solving the Generality Problem for Reliabilism ». ''Philosophical Review'', 128(4), 463-509.</ref> ===== Le cohérentisme perceptuel : la justification comme cohérence systémique ===== '''Le rejet de la structure fondationnaliste''' Le ''cohérentisme'' représente l'alternative architecturale majeure au fondationnalisme. Selon le cohérentisme, il n'existe pas de croyances de base qui seraient immédiatement justifiées indépendamment d'autres croyances. Au contraire, toutes les croyances obtiennent leur justification de leur ''cohérence'' avec l'ensemble du système de croyances du sujet.<ref>BonJour, L. (1985). ''The Structure of Empirical Knowledge''. Harvard University Press, chap. 5-6.</ref> Une croyance est justifiée dans la mesure où elle s'intègre harmonieusement, sans contradiction ni tension, avec les autres croyances que le sujet possède. La justification est donc une propriété holistique et systémique — elle dépend de la structure globale du système de croyances, et non de relations locales et linéaires entre croyances individuelles.<ref>Lehrer, K. (1990). ''Theory of Knowledge''. Westview Press.</ref> '''Application controversée à la justification perceptuelle''' L'application du cohérentisme à la justification perceptuelle est controversée et contre-intuitive. Selon le cohérentisme strict, même les croyances perceptuelles les plus simples et directes ne sont pas immédiatement justifiées par l'expérience perceptuelle. Au contraire, une croyance perceptuelle est justifiée seulement dans la mesure où elle cohère avec l'ensemble des autres croyances du sujet — y compris les croyances sur la fiabilité de la perception, sur les conditions d'observation, sur les propriétés des objets, etc. Cette position semble s'éloigner considérablement de notre compréhension intuitive de la justification perceptuelle. Il semble qu'une expérience perceptuelle claire et distincte puisse justifier une croyance même si cette croyance ne cohère pas parfaitement avec le reste du système de croyances — par exemple, quand la perception révèle quelque chose de surprenant qui contredit nos attentes antérieures.<ref>Pollock, J. (1986). ''Contemporary Theories of Knowledge''. Rowman & Littlefield.</ref> '''La réponse cohérentiste : l'expérience comme croyance spontanée''' Certains cohérentistes répondent en affirmant que l'expérience perceptuelle elle-même doit être conceptualisée comme générant spontanément des croyances perceptuelles immédiates, qui entrent alors dans des relations de cohérence avec les autres croyances. L'expérience ne justifie pas directement la croyance perceptuelle, mais elle produit causalement une croyance perceptuelle spontanée, qui obtient ensuite sa justification de sa cohérence avec le système.<ref>Haack, S. (1993). ''Evidence and Inquiry: Towards Reconstruction in Epistemology''. Blackwell.</ref> Cependant, cette réponse semble affaiblir la distinction entre le rôle causal et le rôle justificatoire de l'expérience, et ne rend peut-être pas pleinement compte de l'intuition que l'expérience possède un rôle épistémique spécial et direct dans la justification des croyances perceptuelles. ===== L'internalisme versus l'externalisme dans la justification perceptuelle ===== '''L'axe fondamental du débat contemporain''' Le débat contemporain sur la justification perceptuelle est structuré par une distinction fondamentale entre deux orientations théoriques : l''internalisme'' et l''externalisme''. Selon l'internalisme, les facteurs qui déterminent si une croyance est justifiée doivent être ''accessibles par introspection'' au sujet — c'est-à-dire que le sujet doit pouvoir, par simple réflexion consciente, accéder aux facteurs qui confèrent la justification à sa croyance. Pour les internalistes, la justification d'une croyance perceptuelle dépend uniquement du caractère phénoménal de l'expérience et des autres états mentaux conscients du sujet.<ref>BonJour, L. & Sosa, E. (2003). ''Epistemic Justification: Internalism vs. Externalism, Foundations vs. Virtues''. Blackwell.</ref> Selon l'externalisme, par contraste, les facteurs qui déterminent la justification peuvent inclure des éléments qui ne sont pas accessibles à l'introspection du sujet. La fiabilité objective du processus perceptuel, les conditions causales qui ont produit l'expérience, les relations nomologiques entre l'expérience et l'environnement — tous ces facteurs peuvent jouer un rôle dans la détermination de la justification, même si le sujet ne peut pas y accéder par simple réflexion.<ref>Goldman, A. I. (1999). « Internalism Exposed ». ''Journal of Philosophy'', 96(6), 271-293.</ref> '''Les arguments en faveur de l'internalisme''' Les internalistes avancent plusieurs arguments puissants. D'abord, l'internalisme capture l'intuition que la justification épistémique est liée à la ''responsabilité épistémique'' — un sujet est justifié dans une croyance s'il a satisfait ses obligations épistémiques, et ces obligations ne peuvent porter que sur des facteurs auxquels le sujet a accès. Deuxièmement, l'internalisme explique pourquoi deux sujets dans des états mentaux phénoménalement identiques — par exemple, un sujet normal et un sujet victime d'un « démon malin » qui produit des expériences systématiquement trompeuses — possèdent le même degré de justification pour leurs croyances perceptuelles. Puisque leurs perspectives internes sont identiques, ils sont également justifiés épistémiquement, même si l'un possède des croyances vraies et l'autre des croyances fausses.<ref>Fumerton, R. (1995). ''Metaepistemology and Skepticism''. Rowman & Littlefield.</ref> '''Les arguments en faveur de l'externalisme''' Les externalistes répondent que l'internalisme rend la justification trop facile à obtenir et trop déconnectée de la vérité. Si la justification dépend uniquement de facteurs internes, alors un sujet systématiquement trompé par un démon malin pourrait posséder des croyances parfaitement justifiées mais entièrement fausses. Cela semble affaiblir le lien crucial entre justification et vérité.<ref>Goldman, A. I. (1986). ''Epistemology and Cognition''. Harvard University Press.</ref> De plus, l'externalisme capture l'intuition que la justification perceptuelle dépend réellement de la fiabilité objective de nos processus perceptuels. Quand nous évaluons si quelqu'un est justifié dans une croyance perceptuelle, nous nous soucions réellement de savoir si son système perceptuel fonctionne correctement et de manière fiable, non pas simplement de ce à quoi ressemble son expérience de l'intérieur.<ref>Bergmann, M. (2006). ''Justification Without Awareness''. Oxford University Press.</ref> ===== Conclusion : la pluralité persistante des théories de la justification perceptuelle ===== Le débat sur la justification perceptuelle demeure vivant et philosophiquement fécond. Chaque approche — fondationnalisme, cohérentisme, fiabilisme, conservatisme phénoménal — possède des forces théoriques et rencontre des difficultés caractéristiques. Aucune théorie ne fait actuellement consensus dans la communauté épistémologique.<ref>Bernecker, S. & Pritchard, D. (dir.) (2011). ''The Routledge Companion to Epistemology''. Routledge, partie IV.</ref> Cette pluralité persistante suggère peut-être que la notion même de « justification » est plurivoque — qu'il existe plusieurs notions légitimes mais distinctes de justification épistémique, chacune capturant un aspect important mais partiel de notre concept intuitif. Une théorie adéquate de la justification perceptuelle devra peut-être reconnaître cette pluralité conceptuelle et articuler les relations entre ces différentes notions de justification.<ref>Alston, W. P. (2005). ''Beyond "Justification": Dimensions of Epistemic Evaluation''. Cornell University Press.</ref> ==== 4.4 Empirisme et rationalisme : les sources de la connaissance ==== ===== Introduction : le débat fondamental sur l'origine de la connaissance ===== L'une des controverses les plus anciennes et les plus fondamentales en épistémologie concerne la question primaire des sources de notre connaissance : d'où provient notre savoir sur le monde ? Comment acquérons-nous nos concepts et nos croyances ? Cette interrogation structurante a donné naissance à deux grandes traditions philosophiques concurrentes dans la philosophie moderne : l'''empirisme'' et le ''rationalisme''.<ref>Markie, P. (2004). « Rationalism vs. Empiricism ». ''Stanford Encyclopedia of Philosophy'', E. N. Zalta (dir.). https://plato.stanford.edu/entries/rationalism-empiricism/</ref> Le rationalisme soutient que la raison constitue la source principale ou privilégiée de notre connaissance substantielle, et que certaines vérités peuvent être connues indépendamment de l'expérience sensible, par la seule réflexion rationnelle. L'empirisme, par contraste, affirme que toute notre connaissance factuelle provient de l'expérience sensible, et que l'esprit ne possède aucune connaissance substantielle antérieure à l'expérience perceptuelle. Ces deux positions s'opposent radicalement quant à l'architecture fondamentale de la justification épistémique et quant à la nature des sources primaires de notre savoir.<ref>Audi, R. (2011). ''Epistemology : A Contemporary Introduction to the Theory of Knowledge'', 3<sup>e</sup> édition. Routledge, chap. 6-7.</ref> ===== Le rationalisme : la raison comme source privilégiée de connaissance ===== '''Les thèses fondamentales du rationalisme classique''' Le rationalisme, dont les représentants majeurs incluent René Descartes (1596-1650), Baruch Spinoza (1632-1677) et Gottfried Wilhelm Leibniz (1646-1716), défend plusieurs thèses épistémologiques distinctes mais profondément interconnectées. La première et la plus centrale constitue la ''thèse de l'intuition et de la déduction'' : certaines propositions substantielles et informationnelles peuvent être connues par intuition rationnelle immédiate et par déduction logique rigoureuse, sans recourir en aucune manière à l'expérience sensible.<ref>Descartes, R. (1641). ''Méditations métaphysiques'', trad. fr. Duc de Luynes. Paris : Librairie générale française, 1990.</ref> L'intuition rationnelle désigne ici non pas un pressentiment vague ou une conjecture incertaine, mais une saisie intellectuelle immédiate, perspicace et indubitablement certaine de la vérité d'une proposition. Descartes illustre cette capacité rationnelle par sa célèbre formulation « ''Cogito, ergo sum'' » (« Je pense, donc je suis ») : la vérité de l'existence du sujet pensant s'impose à l'esprit avec une évidence immédiate et irrésistible qui ne dépend d'aucune expérience sensible externe ou d'aucune observation du monde physique.<ref>Descartes, R. (1637). ''Discours de la méthode''. Paris : Garnier-Flammarion, 1992, partie IV.</ref> La déduction rationnelle, quant à elle, constitue le processus par lequel nous dérivons logiquement de nouvelles connaissances à partir de vérités initialement intuitionnées ou préalablement établies. Si nous intuitionnons que « tout effet nécessite une cause » et que « le mouvement constitue un effet observable », nous pouvons déduire rigoureusement que « le mouvement possède une cause ». Cette connaissance dérivée par déduction logique demeure tout aussi certaine et indépendante de l'expérience empirique que les prémisses rationnelles dont elle procède, car la certitude se transmet de manière nécessaire par la validité logique. '''La doctrine des idées innées : structure naturelle de l'esprit''' Une seconde thèse épistémologiquement cruciale du rationalisme concerne l'existence d'''idées innées'' — c'est-à-dire de concepts fondamentaux ou de connaissances élémentaires que l'esprit possède naturellement et originairement, antérieurement à toute expérience perceptuelle. Cette doctrine, défendue avec conviction par Descartes et développée sophistiquement par Leibniz, affirme que certaines notions conceptuelles fondamentales (Dieu, la substance, la causalité, l'identité logique, l'infinité) ne peuvent pas être dérivées empiriquement de l'expérience sensible fragmentaire, mais doivent être présentes dans l'esprit de manière innée, constitutive et antécédente.<ref>Leibniz, G. W. (1704). ''Nouveaux essais sur l'entendement humain''. Paris : Garnier-Flammarion, 1990, préface.</ref> Leibniz propose une métaphore d'une clarté et d'une pertinence remarquables : l'esprit n'est pas une « table rase » (''tabula rasa'') entièrement vide et indifférenciée, mais plutôt comparable à un bloc de marbre dont les veines naturelles préfigurent et prédéterminent les formes qui pourront en être extraites. De manière analogue, notre esprit possède des structures conceptuelles et rationnelles innées qui orientent, organisent et contraignent notre compréhension du monde. Sans ces structures préexistantes et innées, nous ne pourrions même pas former les concepts généraux et abstraits que nous semblons tirer de l'expérience sensible fragmentaire et particulière.<ref>Leibniz, G. W. (1704). ''Nouveaux essais sur l'entendement humain''. Paris : Garnier-Flammarion, 1990, livre I, chap. 1.</ref> '''Les avantages explicatifs du rationalisme''' Le rationalisme possède plusieurs avantages théoriques et explicatifs importants. D'abord, il rend compte élégamment de comment nous pouvons posséder des connaissances qui sont nécessaires et universelles — des vérités qui ne sont pas simplement vraies dans les cas particuliers que nous avons observés, mais qui doivent être vraies dans tous les cas possibles. Les vérités mathématiques (« 2 + 2 = 4 », « la somme des angles d'un triangle euclidien égale 180 degrés ») et les principes logiques fondamentaux (« une chose ne peut simultanément être et ne pas être ») semblent posséder ce caractère intrinsèque de nécessité qui transcende entièrement toute expérience particulière ou observation contingente. Deuxièmement, le rationalisme explique la certitude épistémique absolutiste que nous éprouvons concernant certaines propositions théoriques. Quand nous intuitionnons rationnellement qu'une proposition est vraie, nous ne la croyons pas simplement avec probabilité ou avec un degré de confiance variable — nous la savons avec une certitude indubitable et inébranlable qui ne peut être ébranlée par aucune observation ultérieure ou aucune expérience contraire. ===== L'empirisme : l'expérience comme source unique et suffisante de connaissance ===== '''Les thèses fondamentales de l'empirisme britannique''' L'empirisme, dont les représentants majeurs incluent John Locke (1632-1704), George Berkeley (1685-1753) et David Hume (1711-1776), constitue la position philosophique antithétique au rationalisme. Selon l'empirisme, toute notre connaissance substantive et informationnelle provient de l'expérience sensible, et aucune connaissance factuelle ne peut être acquise par la seule raison indépendamment de l'expérience perceptuelle empirique.<ref>Locke, J. (1690). ''Essai sur l'entendement humain'', trad. fr. J.-M. Vienne. Paris : Vrin, 2001.</ref> La thèse centrale et définitoire de l'empirisme peut s'énoncer avec clarté ainsi : l'esprit humain à la naissance constitue une ''tabula rasa'' — une table rase, une page blanche ou un tableau vierge dépourvu d'aucune inscription préalable, sans aucune idée innée et sans aucune structure conceptuelle pré-constituée. Toutes nos idées et tous nos concepts sont acquis progressivement et graduellement par l'expérience sensorielle — par la vision, l'audition, le toucher, le goût et l'odorat — et par la réflexion interne sur les opérations de notre propre esprit. Ce que nous appelons « connaissance » n'est rien d'autre que la collection systématique, la combinaison originale et la généralisation progressive des données sensorielles brutes que nous recevons de l'expérience externe.<ref>Locke, J. (1690). ''Essai sur l'entendement humain'', trad. fr. J.-M. Vienne. Paris : Vrin, 2001, livre II, chap. 1.</ref> '''L'argument lockien contre les idées innées : le critère d'universalité''' John Locke, dans le premier livre de son influent ''Essai sur l'entendement humain'' (1690), développe une critique systématique, rigoureuse et multifacette de la doctrine rationaliste des idées innées. Son argument principal et le plus dévastateur repose sur le principe épistémologique suivant : si une idée ou une connaissance est véritablement innée — si elle existe réellement dans l'esprit antérieurement à toute expérience — elle doit être ''universellement présente'' — c'est-à-dire présente sans exception dans tous les esprits humains, quelle que soit leur condition, leur culture ou leur développement intellectuel. Or, observe Locke avec une perspicacité remarquable, aucune proposition prétendue innée ne satisfait à ce critère rigoureux d'universalité.<ref>Locke, J. (1690). ''Essai sur l'entendement humain'', trad. fr. J.-M. Vienne. Paris : Vrin, 2001, livre I, chap. 2-4.</ref> Considérez les principes logiques que les rationalistes prétendent innés et universels, comme le principe d'identité (« ce qui est, est ») ou le principe de non-contradiction (« une même chose ne peut simultanément être et ne pas être »). Les enfants en bas âge et les personnes intellectuellement handicapées ne possèdent manifestement aucune conscience explicite, aucune compréhension cognitive de ces principes. Si ces principes étaient véritablement innés dans la structure profonde de l'esprit, ils devraient être conscients et accessibles dans tous les esprits dès la naissance, sans nécessité de développement ou d'éducation. Les rationalistes tentent de répondre en affirmant que les idées innées peuvent exister dans l'esprit sans être conscientes — elles sont présentes de manière latente, implicite ou virtuelle, et l'éducation ne fait que les rendre explicites, actuelles et conscientes. Mais Locke rejette cette réponse comme fondamentalement incohérente et conceptuellement intenable : une idée dont nous ne sommes pas conscients, une idée qui n'existe qu'en puissance latente sans actualité consciente, n'est tout simplement pas réellement une idée que nous ''possédons'' au sens propre. Dire qu'une idée est « dans l'esprit » mais demeure inconsciente revient à employer des mots vidés de sens — c'est revenir à l'absurdité de dire qu'elle n'est tout simplement pas dans l'esprit. '''La construction empiriste de la connaissance : idées simples et idées complexes''' Locke propose une explication alternative élégante et systématique de l'origine entière de nos idées qui ne requiert aucune invocation d'idées innées ou de structures rationnelles préexistantes. Selon sa théorie génétique de l'entendement, toutes nos idées — du plus simple au plus complexe, du plus concret au plus abstrait — se divisent en deux catégories fondamentales et exhaustives : les ''idées simples'' et les ''idées complexes''.<ref>Locke, J. (1690). ''Essai sur l'entendement humain'', trad. fr. J.-M. Vienne. Paris : Vrin, 2001, livre II, chap. 2-12.</ref> Les idées simples constituent les unités élémentaires et indécomposables que nous recevons passivement et directement par l'expérience sensorielle externe — la rougeur, la chaleur, la dureté, la mollesse, le froid — ou par la réflexion interne et méditative sur les opérations caractéristiques de notre propre esprit — le doute, la croyance, le désir, la réflexion, la volition. Ces idées simples ne peuvent pas être analysées ou réduites en composants plus élémentaires ; elles constituent les atomes conceptuels irréductibles, les briques primitives dont est construite toute notre connaissance conceptuelle. Les idées complexes, par contraste, sont construites activement, volontairement et combinatoirement par les opérations synthétiques de l'esprit, en assemblant, comparant, distinguant et abstrayant des idées simples préalablement acquises par l'expérience sensorielle. L'idée d'une « montagne d'or » — un concept que nous formons aisément — résulte simplement de la combinaison judicieuse de deux idées simples préalablement acquises par l'expérience perceptuelle : l'idée simple de montagne (acquise en observant des montagnes réelles) et l'idée simple d'or (acquise en observant de l'or réel). Même si nous n'avons jamais observé une montagne d'or dans la réalité physique du monde, nous pouvons former cette idée complexe imaginaire en combinant synthétiquement deux idées simples d'origine empirique indubitable. '''Le scepticisme humien : l'analyse critique des fondements de la connaissance empirique''' David Hume pousse les principes empiristes à leurs conclusions logiques les plus strictes, les plus rigoureuses et les plus sceptiquement radicales. Selon Hume, si toute notre connaissance provient de l'expérience, alors notre connaissance demeure nécessairement limitée à ce que nous avons effectivement et directement observé. Nous ne pouvons jamais savoir avec la certitude démontrée et logique ce qui se passe au-delà de nos observations immédiates, dans le passé non-observé ou dans l'avenir incertain.<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', trad. fr. A. Leroy. Paris : Garnier-Flammarion, 1983.</ref> Le problème philosophique majeur de l'induction illustre de manière lumineuse cette limitation épistémique radicale. Supposez que nous avons observé mille fois, dix mille fois, avec une régularité absolue, que le feu brûle et détruit. Pouvons-nous conclure avec certitude logique et démontrée que le feu brûlera toujours à l'avenir, en toutes circonstances, sans exception ? Selon l'analyse critique de Hume, catégoriquement non. Aucun nombre, aussi grand soit-il, d'observations passées ne peut garantir logiquement ou déductivement qu'une régularité observée se maintiendra invariablement dans le futur. L'inférence du passé au futur présuppose tacitement un principe métaphysique fondamental — le principe de l'uniformité de la nature — l'idée non-démontrée que l'avenir ressemblera au passé. Mais ce principe lui-même ne peut être justifié ni par l'expérience (ce serait un raisonnement vicieusement circulaire) ni par la raison pure (car sa négation n'implique aucune contradiction logique autoréfutante).<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', trad. fr. A. Leroy. Paris : Garnier-Flammarion, 1983, section IV.</ref> Plus philosophiquement perturbant encore est l'analyse huienne de la causalité — l'une des notions les plus fondamentales et les plus ordinaires de la pensée. Quand nous observons qu'un événement A est toujours suivi d'un événement B, nous croyons naturellement et spontanément que A « cause » B — que A produit B, que A est responsable de B. Mais que percevons-nous réellement lors de cette observation ? Uniquement une succession temporelle régulière, répétée et constante — une conjonction constante entre l'événement antécédent A et l'événement conséquent B. Nous ne percevons jamais directement une « connexion nécessaire » invisible, une « puissance causale » occulte, un « pouvoir » mystérieux qui lierait causalement A à B. Cette idée de connexion causale nécessaire et de pouvoir productif ne provient donc pas de l'expérience sensible directe, et elle ne peut être justifiée rationnellement de manière démonstrée. Elle résulte simplement d'une habitude psychologique involontaire : après avoir observé maintes fois la conjonction régulière de A et B, notre esprit développe une disposition psychique à attendre B quand A se produit.<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', trad. fr. A. Leroy. Paris : Garnier-Flammarion, 1983, section VII.</ref> ===== La synthèse kantienne : dépassement de l'opposition binaire ===== '''L'influence réformatrice de Hume sur la pensée kantienne''' Immanuel Kant (1724-1804) affirmera que la lecture des œuvres philosophiques de David Hume l'a « réveillé de son sommeil dogmatique » — c'est-à-dire qu'elle l'a libéré de l'acceptation naïve et non-critique des présuppositions rationalistes cartésiennes dans lesquelles il avait reçu sa formation philosophique initiale. Cependant, Kant ne se convertit nullement simplement à l'empirisme humien et à son scepticisme radical. Au contraire, il développe une position synthétique et novatrice qui prétend dépasser l'opposition apparemment irréconciliable entre rationalisme et empirisme en intégrant les intuitions valides et profondes de chaque tradition dans un cadre théorique plus profond, plus cohérent et plus satisfaisant épistémologiquement.<ref>Kant, I. (1783). ''Prolégomènes à toute métaphysique future qui pourra se présenter comme science'', trad. fr. L. Guillermit. Paris : Vrin, 1986, préface.</ref> '''Les distinctions kantiennes fondamentales : a priori versus a posteriori, analytique versus synthétique''' Kant introduit deux distinctions conceptuelles crucialement importantes qui permettent d'articuler avec une précision remarquable le débat philosophique entre rationalisme et empirisme. La première distinction concerne la ''source épistémique de justification'' d'une proposition :<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, introduction, B1-B3.</ref> * Une proposition est connue ''a priori'' si sa justification rationnelle ne dépend en aucune manière d'une expérience perceptuelle particulière — elle peut être connue et établie comme vraie par la seule réflexion et raisonnement rationnel, entièrement indépendamment de toute observation empirique du monde. * Une proposition est connue ''a posteriori'' si sa justification dépend essentiellement et constitutivement de l'expérience sensible et de l'observation empirique — nous devons observer et interroger le monde pour savoir avec certitude si elle est vraie ou fausse. La seconde distinction fondamentale concerne le ''contenu informatif substantiel'' d'une proposition : * Un jugement est ''analytique'' si le prédicat est conceptuellement et logiquement contenu dans le sujet — la simple analyse et décomposition du concept du sujet révèle déjà le prédicat. Par exemple, « tous les célibataires sont non-mariés » est analytique, car le concept « non-marié » est déjà inclus logiquement et définitionnellement dans le concept « célibataire ». Le prédicat ne nous apprend rien de nouveau sur le sujet. * Un jugement est ''synthétique'' si le prédicat ajoute une information nouvelle et substantielle qui n'était pas déjà contenue analytiquement dans le concept du sujet. Par exemple, « cette table est rouge » est synthétique, car le concept de rougeur n'est pas contenu dans le simple concept de table — cette proposition nous apprend quelque chose de nouveau sur le monde. '''L'innovation révolutionnaire kantienne : la possibilité du synthétique a priori''' Les philosophes et les penseurs antérieurs à Kant avaient généralement supposé que ces deux distinctions coïncident parfaitement et sans exception : tout ce qui est connu a priori serait analytique et n'ajouterait aucune information nouvelle, et tout ce qui est synthétique et informatif serait connu a posteriori par l'expérience. Le rationalisme et l'empirisme ne divergeaient que sur l'étendue quantitative et l'importance relative de nos connaissances analytiques a priori.<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, introduction, B10-B14.</ref> L'innovation révolutionnaire et transformatrice de Kant consiste à affirmer l'existence d'une nouvelle catégorie épistémique jusqu'alors non-reconnue : les ''jugements synthétiques a priori'' — c'est-à-dire des propositions qui sont à la fois informationnellement substantielles et ajoutent du contenu nouveau au monde (synthétiques) ''et'' connaissables indépendamment de l'expérience sensible (a priori). Kant cite comme exemples paradigmatiques et incontestables les vérités mathématiques (« 7 + 5 = 12 », « la ligne droite est le plus court chemin entre deux points ») et les principes fondamentaux de la physique causale (« toute altération dans la nature possède une cause »). Considérez l'énoncé mathématique « 7 + 5 = 12 ». Selon l'analyse kantienne, ce jugement est synthétique, car le concept « 12 » n'est pas analytiquement et logiquement contenu dans les concepts de « 7 » et de « 5 » considérés séparément ou combinés. Pour saisir et reconnaître que sept unités plus cinq unités égalent nécessairement douze unités, nous devons effectuer une opération mentale active de construction — nous devons progressivement et mentalement ajouter cinq unités à sept unités et percevoir intuitivement que le résultat synthétisé est effectivement douze. Cette opération constructive et synthétisante dépasse et transcende la simple analyse conceptuelle et la simple réflexion logique.<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, introduction, B15-B16.</ref> Cependant, ce jugement mathématique demeure également a priori, car nous n'avons manifestement pas besoin de compter empiriquement sept objets concrets et cinq objets concrets pour savoir avec certitude que leur ensemble constitue nécessairement douze objets. La vérité mathématique ne dépend d'aucune observation empirique particulière — elle est universelle, éternelle et nécessaire, vraie dans tous les mondes possibles et tous les univers concevables. '''L'idéalisme transcendantal : résolution du mystère du synthétique a priori''' La question centrale et véritablement cruciale que pose Kant est donc : comment la connaissance synthétique a priori — la connaissance de propositions substantielles et informationnelles qui ne dépendent pourtant pas de l'expérience particulière — est-elle épistémiquement possible ? Comment pouvons-nous posséder des connaissances qui ajoutent de l'information réelle sur le monde et qui demeurent néanmoins indépendantes de toute expérience sensible empirique ?<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, introduction, B19.</ref> La réponse profonde et innovante de Kant constitue ce qu'il appelle magistralement la « révolution copernicienne » en philosophie. Au lieu de présupposer avec la tradition que notre connaissance doit nécessairement se conformer à la structure préexistante des objets externes, Kant propose l'hypothèse métaphysiquement inverse et audacieuse : ce sont précisément les objets de notre expérience qui doivent se conformer et s'adapter à la structure a priori de notre connaissance et de nos facultés cognitives. Nous ne connaissons jamais les choses « en soi » (''Dinge an sich''), telles qu'elles existent en elles-mêmes, indépendamment et détachées de nos facultés cognitives. Nous connaissons exclusivement les choses « pour nous », telles qu'elles ''nous'' apparaissent et se présentent nécessairement structurées et organisées par les formes a priori de notre sensibilité et par les catégories a priori de notre entendement.<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, préface de la seconde édition, Bxvi-Bxviii.</ref> Les formes a priori de la sensibilité — l'espace et le temps — structurent transcendantalement toute notre expérience perceptuelle possible. Nous ne percevons jamais des objets sans structure spatiale organisée et sans structure temporelle organisée, non pas parce que les objets en soi, indépendants de nous, possèdent nécessairement ces propriétés formelles, mais parce que notre faculté sensorielle et perceptuelle ne peut représenter les objets et les événements que sous ces formes a priori de l'espace et du temps. De manière analogue, les catégories a priori de l'entendement — substance, causalité, réciprocité, nécessité, possibilité — structurent transcendantalement toute notre compréhension conceptuelle organisée du monde.<ref>Kant, I. (1781/1787). ''Critique de la raison pure'', trad. fr. A. Tremesaygues et B. Pacaud. Paris : PUF, 2004, Esthétique transcendantale et Analytique transcendantale.</ref> Cette théorie transcendantale explicite comment la connaissance synthétique a priori demeure épistémiquement possible : les vérités synthétiques a priori décrivent non pas les propriétés intrinsèques des choses en soi indépendantes, mais plutôt la structure nécessaire et inévitable que notre faculté cognitive impose de manière constitutive à toute expérience objectale possible. La proposition « toute altération dans la nature possède une cause » est synthétique a priori car elle décrit une condition transcendantalement nécessaire de toute expérience cohérente et ordonnée d'un monde temporel — nous ne pourrions même pas avoir une expérience unifiée et compréhensible d'un univers temporel et changeant sans appliquer nécessairement le concept de causalité. ===== Conclusion : l'héritage durable du débat empirisme-rationalisme ===== Le débat entre rationalisme et empirisme, bien que prenant des formes considérablement transformées et innovantes, demeure vivant et philosophiquement fécond dans l'épistémologie contemporaine. Les descendants conceptuels du rationalisme incluent les théories et les positions qui défendent l'existence de connaissances a priori substantielles et nécessaires — notamment en logique pure, en mathématiques fondamentales et en philosophie métaphysique. Les descendants conceptuels de l'empirisme incluent les théories naturalistes, scientifiques et empiriquement informées qui insistent avec rigueur sur le rôle central et primordial de l'observation empirique systématique et de la méthode expérimentale.<ref>BonJour, L. (1998). ''In Defense of Pure Reason : A Rationalist Account of A Priori Justification''. Cambridge University Press.</ref> La synthèse kantienne, malgré ses difficultés conceptuelles persistantes et ses défis théoriques non-résolus, a établi un cadre conceptuel durable et influent pour articuler et structurer ces questions philosophiques fondamentales. Les distinctions kantiennes entre a priori et a posteriori, entre analytique et synthétique, entre phénomène et chose-en-soi continuent de structurer et d'organiser les débats épistémologiques contemporains, même lorsque les philosophes actuels contestent vigoureusement les réponses spécifiques et les positions particulières que Kant lui-même a proposées.<ref>Guyer, P. & Wood, A. (dir.) (1992). ''The Cambridge Companion to Kant''. Cambridge University Press.</ref> === Chapitre 5 : Le témoignage === ==== 5.1 Épistémologie du témoignage : la confiance et la transmission du savoir ==== ===== Introduction : le témoignage comme source fondamentale de connaissance ===== La majorité de nos connaissances ne provient pas de notre expérience directe du monde, mais du témoignage d'autrui — de ce que d'autres personnes nous disent, nous écrivent ou nous rapportent. Nous n'avons pas personnellement visité toutes les villes dont nous connaissons l'existence, nous n'avons pas assisté aux événements historiques que nous tenons pour établis, nous n'avons pas conduit nous-mêmes les expériences scientifiques dont nous acceptons les résultats. Notre savoir sur l'histoire, la géographie, la science naturelle, l'actualité et même sur la vie intérieure d'autrui dépend de manière massive et constitutive du témoignage — de la parole et de l'écrit d'autres personnes que nous croyons et sur lesquelles nous comptons.<ref>Goldman, A. I. (1999). ''Knowledge in a Social World''. Oxford University Press, p. 100-104.</ref> Cette dépendance épistémique profonde et inévitable soulève des questions philosophiques fondamentales et persistantes. Comment le témoignage peut-il véritablement constituer une source légitime et fiable de connaissance ? Quelles conditions précises doivent être satisfaites pour qu'une croyance formée sur la base du témoignage d'une autre personne soit epistemiquement justifiée ? Le témoignage se limite-t-il à transmettre une connaissance déjà possédée par le locuteur, ou peut-il générer une connaissance nouvelle et authentique chez l'auditeur ? Ces interrogations structurantes organisent ce qu'on appelle l'''épistémologie du témoignage'' — une branche centrale et florissante de l'épistémologie sociale contemporaine qui explore les fondements épistémologiques de nos pratiques communicatives et de nos dépendances interpersonnelles en matière de savoir.<ref>Lackey, J. & Sosa, E. (dir.) (2006). ''The Epistemology of Testimony''. Oxford University Press.</ref> ===== Le réductionnisme : la réduction du témoignage à d'autres sources épistémiques ===== '''La position réductionniste : structure générale''' Le ''réductionnisme'' en épistémologie du témoignage défend la thèse que la justification testimoniale ne constitue pas une source épistémique fondamentale ou primitive, mais peut et doit être réduite ou reconstituée à partir d'autres sources épistémiques plus basiques et antérieurement mieux comprises — principalement la perception sensorielle, la mémoire autobiographique et l'inférence inductive. Selon cette approche, un auditeur ne peut être rationnellement justifié à croire le témoignage d'un locuteur que s'il possède des raisons positives et indépendantes de penser que ce témoignage particulier, ou le locuteur particulier, ou la pratique testimoniale en général, constituent des sources fiables de croyances vraies.<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', trad. fr. A. Leroy. Paris : Garnier-Flammarion, 1983, section X.</ref> David Hume constitue historiquement le représentant paradigmatique et le plus influent du réductionnisme testimonial classique. Selon l'analyse huienne, notre confiance naturelle dans le témoignage d'autrui ne se justifie épistémiquement que par appel à notre observation répétée et accumulée de la conformité générale entre les témoignages passés et les faits observés de manière indépendante. Nous croyons ce que les autres personnes nous disent simplement parce que nous avons constaté empiriquement, à travers de nombreuses expériences antérieures étendues, que les témoignages humains sont généralement et statistiquement véridiques. La justification de la croyance testimoniale se réduit donc à un raisonnement inductif fondé rigoureusement sur l'expérience personnelle et l'observation passée accumulée.<ref>Hume, D. (1748). ''Enquête sur l'entendement humain'', trad. fr. A. Leroy. Paris : Garnier-Flammarion, 1983, section X, § 4-5.</ref> '''Deux variantes du réductionnisme : global et local''' On distingue couramment deux variantes du réductionnisme qui diffèrent significativement par leur degré d'exigence épistémique et de sophistication. Le ''réductionnisme global'' soutient que pour être justifié à accepter un témoignage particulier quelconque, l'auditeur doit posséder des raisons positives concernant la fiabilité générale du ''témoignage en tant que pratique sociale'' — c'est-à-dire une évaluation globale de la fiabilité de l'activité humaine de témoigner. L'auditeur doit avoir observé et accumulé suffisamment de cas où des témoignages se sont avérés véridiques pour pouvoir inférer inductivement, avec confiance statistique, que le témoignage présent spécifique est probablement fiable et véridique également.<ref>Fricker, E. (1994). « Against Gullibility ». Dans Matilal, B. K. & Chakrabarti, A. (dir.), ''Knowing from Words''. Kluwer, p. 125-161.</ref> Le ''réductionnisme local'', plus modéré dans ses exigences, ne demande pas que l'auditeur possède des raisons positives générales concernant la fiabilité du témoignage en tant que pratique universelle, mais seulement des raisons positives et spécifiques concernant la fiabilité du ''locuteur particulier'' dans la ''situation particulière'' présente. L'auditeur doit évaluer activement et avec vigilance la crédibilité épistémique spécifique du locuteur — en observant et interprétant son comportement verbomoteur, son intonation et son assurance, sa cohérence interne et sa cohérence avec d'autres sources informatives, sa compétence apparente et démontrée sur le sujet — et ne devrait accepter le témoignage que si cette évaluation critique produit des raisons positives suffisantes de confiance fiduciaire envers le locuteur particulier.<ref>Fricker, E. (1995). « Telling and Trusting : Reductionism and Anti-Reductionism in the Epistemology of Testimony ». ''Mind'', 104(414), 393-411.</ref> '''Objections majeures au réductionnisme : circularité viciée et acquisition infantile''' Le réductionnisme rencontre plusieurs objections puissantes et conceptuellement troublantes qui questionnent sa viabilité théorique. D'abord, l'objection de la ''circularité vicieuse'' : pour acquérir les raisons inductives et les justifications que le réductionnisme considère comme nécessaires — c'est-à-dire pour accumuler suffisamment d'observations particulières de corrélation entre témoignage et vérité objective — nous devons déjà posséder une quantité considérable de connaissances factuelles sur le monde. Mais comment avons-nous initialement acquis ces connaissances factiques préalables ? Si c'est précisément par le témoignage d'autres personnes, alors nous sommes pris dans un cercle épistémique apparemment inévitable : nous aurions besoin de raisons inductives concernant le témoignage pour être justifiés à accepter le témoignage, mais nous aurions besoin d'accepter le témoignage pour acquérir ces raisons inductives. Le réductionnisme semble donc soit vicieusement circulaire, soit conduire à une régression infinie de justifications testimoniales.<ref>Coady, C. A. J. (1992). ''Testimony : A Philosophical Study''. Oxford University Press, p. 79-100.</ref> Deuxièmement, l'objection de l'''acquisition infantile de connaissance'' : les jeunes enfants — particulièrement en bas âge — acquièrent manifestement une quantité colossale de connaissances factuelles authentiques par le témoignage de leurs parents, de leurs éducateurs et de leur entourage familial et social. Ces enfants constituent clairement des cas de personnes qui possèdent une connaissance attestée et irrécusable. Pourtant, ces enfants ne possèdent manifestement pas l'expérience extensive du monde, ni les capacités cognitives sophistiquées d'évaluation critique et de pensée inductive, que le réductionnisme semble exiger pour justifier rationnellement l'acceptation du témoignage. Un enfant de trois ans qui apprend que les girafes possèdent un cou extraordinairement long en écoutant patiemment ses parents ne peut absolument pas avoir accumulé suffisamment d'observations épistémologiquement pertinentes confirmant la fiabilité générale du témoignage parental pour satisfaire aux exigences exigeantes du réductionnisme global ou même local. Si le réductionnisme était véritablement correct, les enfants jeunes ne pourraient tout simplement pas acquérir aucune connaissance testimoniale — conclusion qui semble manifestement fausse et contraire à nos observations empiriques évidentes de l'apprentissage enfantin.<ref>Audi, R. (1997). « The Place of Testimony in the Fabric of Knowledge and Justification ». ''American Philosophical Quarterly'', 34(4), 405-422.</ref> ===== L'anti-réductionnisme : le témoignage comme source épistémique primitive ===== '''La thèse anti-réductionniste fondamentale et ses présupposés''' L'''anti-réductionnisme'' (aussi appelé ''non-réductionnisme'') soutient la position rivale que le témoignage constitue une ''source épistémique fondamentale et primitive'', au même titre structurel que la perception sensible, la mémoire autobiographique ou le raisonnement déductif. Aucune de ces sources — ni perception, ni mémoire, ni raisonnement — ne peut être réduite ou reconstruite à partir d'autres sources plus basiques. De manière similaire, le témoignage représente une voie irréductible et autonome d'accès à la connaissance. Selon cette approche, un auditeur peut rationnellement être justifié à croire le témoignage d'un locuteur sans posséder de raisons positives indépendantes préalables concernant la fiabilité du locuteur particulier ou du témoignage en général. La réception d'un témoignage sincère et clairement énoncé suffit, en l'absence de raisons positives contraires spécifiques ou de ce qu'on appelle des ''défaiseurs'', à conférer une justification ''prima facie'' (une justification présomptive et provisoire, susceptible d'être défaite) à la croyance testimoniale formée par l'auditeur.<ref>Reid, T. (1764). ''An Inquiry into the Human Mind on the Principles of Common Sense'' (trad. fr. : ''Recherches sur l'entendement humain d'après les principes du sens commun''). Paris : Vrin, 2012, chap. VI, section XXIV.</ref> Thomas Reid, philosophe écossais du dix-huitième siècle, représente historiquement et philosophiquement le représentant paradigmatique de la position anti-réductionniste. Selon Reid, la nature humaine possède deux principes psychologiques et communicatifs fondamentaux, innés et constitutifs, qui rendent la pratique du témoignage épistémiquement fiable et rationnellement acceptable par défaut : le ''principe de véracité'' dispose naturellement les locuteurs humains à dire la vérité et à rapporter consciencieusement ce qu'ils savent, tandis que le ''principe de crédulité'' dispose naturellement les auditeurs humains à croire ce qu'on leur dit honnêtement et sincèrement. Ces deux dispositions naturelles ne requièrent aucune justification inductive préalable ni aucune validation empirique — elles constituent des aspects constitutifs et fondamentaux de notre nature sociale, communicative et épistémique. Accepter le témoignage d'autrui représente donc une attitude épistémiquement rationnelle et justifiée par défaut, une option de base qui ne nécessite pas de raisons positives supplémentaires ou de preuves additionnelles pour être justifiée.<ref>Reid, T. (1764). ''An Inquiry into the Human Mind on the Principles of Common Sense''. Chap. VI, section XXIV.</ref> '''La structure présomptive de la justification testimoniale : défaiseurs et contexte''' Les anti-réductionnistes contemporains reconnaissent généralement que la justification testimoniale, bien que fondamentale, n'est pas absolue, irrévocable ou imperméable à la critique rationnelle. La justification n'est que ''prima facie'' ou ''présomptive'' — c'est-à-dire provisoire et révocable. La confiance épistémique par défaut dans le témoignage peut être rationnellement ''défaite'' ou ''annulée'' par la présence de ''défaiseurs'' — c'est-à-dire de raisons positives, de preuves ou d'indices donnant à l'auditeur des motifs légitimes de douter de la véracité et de la fiabilité du témoignage particulier. Si l'auditeur possède des évidences convaincantes que le locuteur est un menteur habituel et dénué de fiabilité, ou que le témoignage présent contredit d'autres témoignages provenant de sources fiables et indépendantes, ou que le locuteur possède des motivations évidentes et manifestes de tromper intentionnellement, alors la justification prima facie est raisonnablement défaite et annulée, et l'auditeur n'est plus épistémiquement justifié à accepter et à croire le témoignage.<ref>Burge, T. (1993). « Content Preservation ». ''Philosophical Review'', 102(4), 457-488.</ref> Cette structure architecturalement présomptive et défaisible de la justification testimoniale — justification par défaut et confiance automatique en l'absence de défaiseurs identifiables — distingue fondamentalement l'anti-réductionnisme du réductionnisme. Le réductionniste exige activement des raisons positives pour croire et pour justifier la croyance ; l'anti-réductionniste exige seulement l'absence de raisons positives contraires ou de défaiseurs pour rationnellement maintenir et ne pas abandonner la croyance. Cette différence architecturale profonde dans la structure de la justification reflète deux conceptions distincts et irréconciliables de la rationalité épistémique et de l'organisation fondamentale de la justification épistémique chez les êtres humains. '''Objections à l'anti-réductionnisme : crédulité excessive et environnements hostiles''' L'anti-réductionnisme rencontre lui aussi des objections sérieuses et philosophiquement significatives qui questionnent sa plausibilité théorique. L'objection principale et la plus persistante concerne le problème de la ''crédulité excessive'' ou de l'''acceptation trop libérale'' : si nous sommes justifiés à croire tout témoignage en l'absence de défaiseurs explicites et identifiés, alors nous semblons rationnellement justifiés à croire des témoignages manifestement douteux ou extraordinaires dans des contextes épistémiques où nous manquons simplement d'information pertinente pour identifier des défaiseurs appropriés. Supposez qu'un étranger rencontré par hasard dans la rue vous affirme qu'il a observé et rencontré personnellement un extraterrestre physiquement présent hier soir. Si vous ne possédez aucune information spécifique sur cette personne, aucune connaissance préalable de sa réputation ou de sa fiabilité, aucune enquête sur les circonstances supposées, alors vous ne possédez aucun défaiseur explicite ou identifié. L'anti-réductionnisme semblerait donc vous dire que vous êtes rationnellement justifié à croire ce témoignage extraordinaire et hautement implausible — conclusion qui paraît epistermatiquement irresponsable et contraire à nos intuitions normatives sur la pensée critique rationnelle.<ref>Fricker, E. (2006). « Testimony and Epistemic Autonomy ». Dans Lackey, J. & Sosa, E. (dir.), ''The Epistemology of Testimony'', p. 225-250. Oxford University Press.</ref> De plus, dans les ''contextes épistémiquement hostiles'' ou ''environnements épistémiquement nuisibles'' — des contextes informationnels où la désinformation organisée, la propagande délibérée, les faux témoignages systématiques et les manipulations informationnelles sont répandus — la confiance par défaut en témoignages non-interrogés semble dangereusement naïve et épistémiquement imprudente. À l'ère numérique contemporaine, où les contenus informationnels en ligne cherchent fréquemment à manipuler plutôt qu'à informer véridiquement, où les réseaux sociaux propagent massivement la désinformation, où les bulles épistémiques et les chambres d'écho fragmentent notre accès à l'information véridique, accepter les témoignages par défaut sans évaluation critique développée semble exposer l'auditeur à des risques épistémiques considérables, évitables et prévisibles.<ref>Nguyen, C. T. (2020). « Echo Chambers and Epistemic Bubbles ». ''Episteme'', 17(2), 141-161.</ref> ===== La transmission versus la génération de connaissance testimoniale ===== '''Le débat transmission-génération : enjeux et structure''' Un second débat central et philosophiquement fécond en épistémologie du témoignage concerne la question métaphysiquement importante de savoir si le témoignage ''transmet'' simplement une connaissance préexistante du locuteur vers l'auditeur, ou s'il peut ''générer'' ou ''créer'' une connaissance nouvelle et authentique chez l'auditeur qui ne préexistait pas chez le locuteur. Selon la ''thèse de transmission'', l'auditeur ne peut rationnellement acquérir une connaissance testimoniale authentique que si et seulement si le locuteur possédait déjà cette même connaissance préalablement. Le témoignage préserve, transmet et perpétue la connaissance d'une personne à une autre, mais ne la crée ni ne la génère de manière ex nihilo. Selon la ''thèse de génération'', par contraste profond, l'auditeur peut acquérir une connaissance testimoniale authentique même et précisément dans les cas où le locuteur ne possédait pas de connaissance au sens épistémique strict, pourvu que le témoignage énoncé soit néanmoins véridique et que certaines autres conditions épistémiques appropriées soient satisfaites.<ref>Lackey, J. (2008). ''Learning from Words : Testimony as a Source of Knowledge''. Oxford University Press, p. 48-75.</ref> '''Arguments en faveur de la thèse de transmission''' Les partisans de la thèse de transmission avancent plusieurs arguments intuitifs et conceptuellement importants. D'abord, il semble epistemiquement bizarre, paradoxal ou même impossible qu'un auditeur puisse posséder et savoir quelque chose d'important que le locuteur lui-même ne savait pas ou ne possédait pas. Si Marie affirme à Jean que le train de 15 heures part de la gare centrale, mais que Marie elle-même ne savait pas réellement et authentiquement que le train part à 15 heures — elle a simplement deviné sans certitude, ou répété sans comprendre quelque chose qu'elle avait vaguement entendu — comment Jean pourrait-il rationnellement acquérir une véritable connaissance que Marie elle-même ne possédait pas ? La connaissance semble devoir se transmettre du locuteur épistémiquement informé vers l'auditeur réceptif, plutôt que d'apparaître miraculeusement chez l'auditeur sans avoir préexisté chez le locuteur informé.<ref>Lackey, J. (1999). « Testimonial Knowledge and Transmission ». ''Philosophical Quarterly'', 49(197), 471-490.</ref> Deuxièmement, si le témoignage pouvait générer et créer de la connaissance ex nihilo, alors la connaissance deviendrait « trop facile » à acquérir et perdrait sa valeur épistémique. Un locuteur totalement ignorant ou complètement dénué de justification épistémique pourrait néanmoins transmettre de la connaissance authentique à un auditeur simplement en émettant par pur hasard ou par chance un témoignage qui s'avère véridique, indépendamment de tout processus cognitif approprié. Cela semble affaiblir dangereusement les standards épistémiques rigoureux et les conditions substantielles exigées pour l'acquisition et l'attribution de la connaissance. '''Arguments contre la transmission : cas lackeyen de témoignages véridiques sans connaissance du locuteur''' Cependant, des philosophes influents comme Jennifer Lackey ont proposé des cas contraires convaincants et détaillés qui semblent démontrer que le témoignage peut effectivement générer et créer de la connaissance même quand le locuteur lui-même ne possédait pas cette connaissance. Considérez le cas particulier suivant, attentivement construit : un professeur d'astronomie enseigne consciencieusement, méthodiquement et rigoureusement à ses étudiants attentifs que la Terre tourne autour du Soleil — une connaissance scientifique établie et confirmée. Le professeur possède toutes les justifications rationnelles appropriées, tous les arguments rigoureux, toutes les preuves empiriques, et sait authentiquement que cette proposition est vraie. Cependant — point crucial — ce professeur souffre d'un ''doute pathologique'' irrationnel et profondément dysfonctionnel en matière de cosmologie. Malgré toutes ses preuves empiriques et tous ses arguments rationnels, il ne peut pas s'empêcher psychologiquement de douter perpétuellement de la vérité de cette proposition, malgré son absence complète de raison justifiée. Selon certaines théories de la connaissance — notamment les théories externalistes et fiabilistes — ce professeur ne ''sait'' pas strictement et véritablement que la Terre tourne autour du Soleil, car il ne possède pas la certitude psychologique appropriée, la confiance, ou d'autres conditions supposées nécessaires pour la connaissance. Pourtant, ses étudiants attentifs, qui acceptent honnêtement son témoignage sans ce doute pathologique dysfonctionnel, semblent acquérir une connaissance authentique et véridique. Si ce raisonnement est correct, alors les étudiants ont effectivement acquis une connaissance que le professeur lui-même ne possédait strictement pas — le témoignage a généré et créé, plutôt que simplement transmis, de la connaissance authentique.<ref>Lackey, J. (1999). « Testimonial Knowledge and Transmission ». ''Philosophical Quarterly'', 49(197), 471-490.</ref> ===== La confiance épistémique et les normes du témoignage ===== '''La notion de confiance épistémique interpersonnelle''' La ''confiance épistémique'' joue un rôle central, constitutif et normativement chargé dans l'épistémologie du témoignage contemporaine. Quand un auditeur accepte et endosse le témoignage d'un locuteur, il n'accomplit pas simplement l'acte psychologique minimaliste de former une croyance causée ou provoquée par le contenu asserté du témoignage — il ''place sa confiance épistémique'' de manière active dans le locuteur, il ''compte sur'' le locuteur, il attend du locuteur qu'il lui fournisse une information véridique et fiable. Cette dimension interpersonnelle, sociale et normativement significative du processus testimonial distingue fondamentalement et qualitativement l'acquisition de croyances testimoniales de l'acquisition alternative de croyances par perception directe ou par inférence logique individuelle.<ref>Faulkner, P. (2011). ''Knowledge on Trust''. Oxford University Press.</ref> La confiance épistémique implique une vulnérabilité épistémique particulière et constitutive : l'auditeur se rend psychologiquement et épistémiquement dépendant du locuteur, et cette dépendance volontairement contractée peut être rationnellement trahie et violée si le locuteur témoigne de manière insincère, malhonnête ou incompétente. Cette vulnérabilité soulève des questions normatives importantes et troublantes : quelles obligations morales et épistémiques le locuteur possède-t-il envers ses auditeurs ? Dans quelles conditions précises un auditeur rationnel est-il justifié de placer sa confiance délibérée dans un locuteur particulier ? '''Les normes du témoignage : quelle est la norme épistémique appropriée ?''' Un débat normatif important et structurant en épistémologie du témoignage concerne la question de savoir quelles normes épistémiques et sociales gouvernent appropriément et justifient la pratique communicative du témoignage. Selon la ''norme de connaissance'', un locuteur ne devrait énoncer un témoignage affirmatif que P que dans les cas où il sait véritablement que P — la connaissance constitue la norme correcte et appropriée pour asserter. Témoigner sans savoir constitue une violation sérieuse d'une norme épistémique constitutive de la pratique testimoniale elle-même et rend le locuteur épistémiquement responsable. Selon la ''norme de justification'', plus permissive et libérale, un locuteur peut légitimement et appropriément témoigner que P s'il possède une justification suffisante et rationnelle pour croire que P — même s'il ne satisfait pas toutes les conditions strictes pour constituer une connaissance authentique. Selon la ''norme de vérité'', la plus libérale et la plus permissive, un locuteur peut propriétement et sans réserve témoigner que P pourvu seulement que P soit vrai objectivement dans le monde — indépendamment entièrement de son état épistémique personnel concernant P.<ref>Goldberg, S. (2015). ''Assertion : On the Philosophical Significance of Assertoric Speech''. Oxford University Press, p. 88-120.</ref> Ces normes distinctes et rivales ont des implications dramatiques et divergentes pour l'évaluation appropriée de la responsabilité épistémique des locuteurs et pour la justification rationnelle des croyances des auditeurs. Si la norme de connaissance est correcte et justifiée, alors un auditeur qui accepte le témoignage d'un locuteur compétent et visiblement sincère peut légitimement présupposer et supposer que le locuteur sait véritablement ce qu'il affirme — et cette présupposition de la connaissance du locuteur renforce considérablement et élève la justification testimoniale de l'auditeur récepteur. ===== Conclusion : vers une épistémologie sociale intégrée et nuancée ===== L'épistémologie du témoignage révèle fondamentalement la dimension profondément sociale, interpersonnelle et collaborative de la connaissance humaine. Notre savoir collectif n'est pas le produit solitaire et autonome d'efforts cognitifs individuels isolés, mais plutôt le fruit d'une vaste et complexe coopération épistémique impliquant la confiance réciproque, la communication authentique et la dépendance mutuelle acceptée. Les débats structurants entre réductionnisme et anti-réductionnisme, entre transmission et génération de connaissance, entre différentes normes épistémiques du témoignage, reflètent des désaccords profonds et persistants sur la nature fondamentale de la rationalité épistémique humaine et sur les conditions métaphysiquement suffisantes et nécessaires pour l'attribution de la connaissance.<ref>Greco, J. (2020). ''The Transmission of Knowledge''. Cambridge University Press.</ref> Une théorie adéquate, complète et satisfaisante de la connaissance testimoniale devra probablement intégrer et synthétiser des éléments philosophiques de plusieurs approches rivales : reconnaître avec les anti-réductionnistes que le témoignage est une source épistémique fondamentalement autonome et primitive, tout en reconnaissant simultanément avec les réductionnistes que l'évaluation critique vigilante et la perspicacité épistémique demeurer importantes et rationnellement exigées, particulièrement dans des contextes épistémiquement hostiles ou informationnellement fragmentés. Elle devra également articuler avec soin les relations complexes entre la connaissance authentique du locuteur, la confiance fiduciaire de l'auditeur, les normes sociales qui structurent la pratique testimoniale, et la vulnérabilité épistémique inévitable qu'implique toute dépendance informationnelle interpersonnelle.<ref>Goldberg, S. (2010). ''Relying on Others : An Essay in Epistemology''. Oxford University Press.</ref> == Notes et références == {{references}} {{AutoCat}} j2o63erzfda7oa16gw2js4zi5s4po7n Dictionnaire de philosophie/État de nature 0 83126 768460 767903 2026-06-24T03:16:53Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768460 wikitext text/x-wiki {{DicoPhilo|État de nature|lecture=oui}} L’expression d’« état de nature » désigne, dans la philosophie politique moderne, la condition hypothétique de l’être humain avant l’instauration de tout pouvoir politique institué, de toute loi positive et de toute organisation juridique stable. Elle s’oppose à l’[[État civil|état civil]] ou « état de société », où l’existence humaine est réglée par des institutions politiques, des lois et des droits positifs. L’« état de nature » n’est presque jamais, chez les philosophes, la description historique d’une période réellement attestée de l’humanité. Il s’agit d’une construction théorique, souvent fictionnelle, destinée à mettre en lumière ce qui fonde la légitimité du pouvoir politique, la nature des droits des individus et les raisons qui rendent nécessaire la sortie de la condition naturelle pour entrer dans un ordre civil. Chez les auteurs modernes, le concept d’état de nature est donc indissociable des théories du [[contrat social]] et du [[droit naturel]].<ref>Voir par exemple Richard Tuck, ''Natural Rights Theories: Their Origin and Development'', Cambridge, Cambridge University Press, 1979, p. 58-84, sur le rôle fondateur de l’état de nature dans le jusnaturalisme moderne.</ref> Dans ce cadre général, l’état de nature a reçu des interprétations très différentes. Chez Hobbes, il est pensé comme un état de guerre de tous contre tous, où la peur de la mort violente rend la vie humaine précaire.<ref>Thomas Hobbes, ''Léviathan : traité de la matière, de la forme et du pouvoir de la république ecclésiastique et civile'', première partie, chap. XIII, trad. François Tricaud, Paris, Sirey, 1971, p. 122-125.</ref> Chez Locke, il est au contraire un état de liberté et d’égalité régulé par la loi naturelle, mais entaché d’« inconvénients » qui justifient l’institution d’un pouvoir politique.<ref>John Locke, ''Traité du gouvernement civil'', chap. II, trad. David Mazel, éd. Simone Goyard-Fabre, Paris, GF Flammarion, 1992, p. 17-20.</ref> Chez Rousseau, il devient une hypothèse anthropologique construite pour critiquer les inégalités sociales et politiques.<ref>Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', dans ''Discours sur l’inégalité suivi de Discours sur les sciences et les arts'', éd. Blaise Bachofen et Bruno Bernardi, Paris, GF Flammarion, 2008, introduction, p. 7-34.</ref> Spinoza et Kant, chacun à leur manière, réélaborent enfin la notion pour repenser le passage du [[droit naturel]] au [[droit]] politique et au [[droit international]].<ref>Immanuel Kant, ''Doctrine du droit'', dans ''La Métaphysique des mœurs'', trad. Alexis Philonenko, Paris, Vrin, 1971, § 41-42, p. 124-130 ; Baruch Spinoza, ''Traité politique'', chap. II-III, trad. Charles Ramond, Paris, PUF, coll. « Quadrige », 2005, p. 76-101.</ref> == 1. Définition et statut conceptuel de l’état de nature == L’état de nature est d’abord défini par une opposition structurante à l’« état civil ». Dire que les hommes se trouvent en état de nature signifie qu’ils n’ont pas encore institué d’[[État]] au sens moderne, c’est-à-dire une autorité politique dotée d’un pouvoir souverain, capable d’édicter des lois obligatoires pour tous, d’exercer un monopole légitime de la coercition et d’assurer la sécurité des personnes et des biens. Dans l’état de nature, il n’existe ni tribunaux, ni police, ni administration : chacun ne dépend que de sa propre force, de sa prudence et de sa capacité à s’allier ou à se défendre. Toutefois, cette absence d’institutions ne signifie pas nécessairement absence de norme. Selon les auteurs, l’état de nature se voit régi par des « lois de nature » (Hobbes, Locke), par un droit naturel compris comme puissance (Spinoza), ou par des principes de raison qui commandent de sortir de cette condition (Kant). La question décisive devient alors la suivante : les lois ou droits de nature suffisent-ils à garantir la sécurité et la justice, ou exigent-ils la médiation d’un pouvoir politique institué ? Il faut ajouter que, pour la plupart des modernes, l’état de nature est une construction hypothétique. Hobbes lui-même ne suppose pas qu’il ait existé comme état historique universel ; il s’agit plutôt d’un modèle idéal-typique qui déduit, à partir de certains traits de la nature humaine (désirs, passions, rationalité limitée, souci de soi), ce qui résulterait de la coexistence d’individus sans pouvoir commun.<ref>Thomas Hobbes, ''Léviathan'', op. cit., chap. XIII, p. 120-123 ; voir aussi Quentin Skinner, ''Reason and Rhetoric in the Philosophy of Hobbes'', Cambridge, Cambridge University Press, 1996, p. 287-306.</ref> Locke, de son côté, admet que des « états de nature » peuvent subsister localement, dans certaines régions du monde ou dans les relations internationales, mais il s’agit alors de configurations partielles plutôt que d’un stade historique global de l’humanité.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. II, § 14, p. 25-26.</ref> Ainsi, l’état de nature n’est pas un « âge d’or » perdu, ni un simple passé révolu ; c’est un dispositif de pensée. Il sert à dégager les droits que l’homme possède en tant qu’être raisonnable avant toute convention, et à montrer pourquoi ces droits exigent, ou non, la création d’un pouvoir politique et la conclusion d’un contrat social. == 2. Genèse historique : droit naturel, guerres civiles et expansion européenne == Le thème de l’état de nature s’inscrit dans la grande tradition moderne du [[droit naturel]], inaugurée, au XVII{{e}} siècle, par Hugo Grotius et Samuel Pufendorf. Grotius, dans son ''De jure belli ac pacis'' (1625), ne décrit pas encore un « état de nature » au sens fort, mais il cherche à fonder, dans la raison humaine, un droit valable « même si Dieu n’existait pas », ce qui inaugure une conception laïcisée du droit naturel.<ref>Hugo Grotius, ''Le droit de la guerre et de la paix'', livre I, chap. I, § 10, trad. Jean Barbeyrac, Paris, PUF, coll. « Léviathan », 1999, p. 88-90.</ref> Samuel Pufendorf radicalise ce projet dans ''De jure naturae et gentium'' (1672). Il décrit un état de nature caractérisé par l’absence d’autorités établies, où les hommes, bien que naturellement sociables, vivent sans organisation politique et sont exposés à l’insécurité. L’état de nature, chez lui, n’est pas identique à la guerre, mais il est un état précaire où la paix n’est pas suffisamment garantie, ce qui impose la création d’un corps politique stable.<ref>Samuel von Pufendorf, ''Du droit de la nature et des gens'', livre II, chap. II, trad. Jean-Louis Thireau, Paris, Vrin, 1993, p. 97-118.</ref> La réflexion sur l’état de nature prend une importance décisive chez Hobbes, Locke et Rousseau dans un contexte marqué par les guerres de religion, la guerre civile anglaise et l’expansion coloniale européenne. La confrontation avec les sociétés amérindiennes, décrites comme « sans gouvernement » ou « sauvages », fournit aux Européens un matériau empirique ambigu : tantôt on y voit une confirmation d’un état de nature violent (Hobbes), tantôt l’image d’une forme de vie simple et relativement pacifique (Rousseau, certains voyageurs).<ref>Anthony Pagden, ''The Fall of Natural Man: The American Indian and the Origins of Comparative Ethnology'', Cambridge, Cambridge University Press, 1982, p. 15-46.</ref> L’état de nature devient ainsi un outil pour repenser la légitimité de l’État : s’il n’existe ni droit divin, ni hiérarchie naturelle des conditions sociales, qu’est-ce qui peut bien autoriser un homme à commander à d’autres ? La réponse contractuelle consiste à dire : l’autorité naît d’un accord libre des individus sortant de l’état de nature pour instituer un pouvoir commun. La manière dont cet accord est décrit – abandon total de droits chez Hobbes, délégation conditionnelle chez Locke, association d’égal à égal chez Rousseau – dépend directement de la conception de l’état de nature que chaque auteur adopte. == 3. Hobbes : l’état de nature comme guerre de tous contre tous == Chez Thomas Hobbes (1588-1679), l’état de nature est défini à partir d’une anthropologie pessimiste : les hommes sont naturellement égaux par leurs forces et leurs facultés, ils désirent tous des biens limités et chacun craint la mort violente. Cette égalité alimente la rivalité, la méfiance et la recherche de prééminence, de sorte que, tant qu’aucun pouvoir commun ne s’impose, « les hommes vivent sans un pouvoir commun qui les tienne en respect » et se trouvent dans une condition qui équivaut à une guerre « de chacun contre chacun » (''bellum omnium contra omnes'').<ref>Thomas Hobbes, ''Léviathan'', op. cit., chap. XIII, p. 122-125.</ref> Hobbes insiste sur le caractère total de cette guerre : elle ne se réduit pas à des combats permanents, mais décrit un état de méfiance et d’hostilité tel que chacun est prêt à user de la violence à tout moment. Dans cette condition, il n’y a ni industrie durable, ni commerce sûr, ni arts, ni science stable, ni « société » au sens plein, mais une peur constante, et la vie humaine y est exposée à la menace permanente de la mort violente.<ref>Pasquale Pasquino, « Thomas Hobbes : la condition naturelle de l’humanité », ''Revue française de science politique'', vol. 44, n{{o}} 2, 1994, p. 197-215.</ref> L’état de nature n’est cependant pas un chaos sans règle. Hobbes distingue le « droit de nature », qui est la liberté pour chacun d’user de sa puissance comme il l’entend pour se conserver, et les « lois de nature », qui sont des préceptes de raison enjoignant de rechercher la paix quand elle est possible, de renoncer à une part de son droit pour sortir de la guerre, de tenir ses engagements, etc.<ref>Thomas Hobbes, ''Léviathan'', op. cit., chap. XIV-XV, p. 126-143.</ref> Mais ces lois de nature ne sont obligatoires que « en conscience » : tant qu’il n’existe pas de pouvoir souverain pour les faire respecter, chacun reste juge de ce qui est nécessaire à sa conservation et peut toujours revenir à l’usage violent de son droit de nature. C’est pourquoi la sortie de l’état de nature prend, chez Hobbes, la forme d’une double décision rationnelle : les hommes conviennent, par contrat, de transférer leur droit de se gouverner eux-mêmes à un tiers (ou à une assemblée) qui devient souverain, et promettent de se conformer à ses lois. Le souverain n’est pas lui-même partie au contrat : il est institué par l’accord des sujets, et sa puissance doit être absolue, faute de quoi la société risque de retomber dans la guerre civile.<ref>Noël Malcolm, ''Aspects of Hobbes'', Oxford, Clarendon Press, 2002, chap. 10, p. 432-457.</ref> L’état civil n’annule pas tout trait de l’état de nature, mais il en neutralise la violence par la peur de la sanction souveraine. Enfin, Hobbes généralise cette opposition à l’échelle des relations internationales : entre États souverains, il n’existe pas d’autorité supérieure ; ils se trouvent donc, les uns à l’égard des autres, dans un état de nature, c’est-à-dire dans une situation d’hostilité latente, parfois ouverte, même si des accords et des traités peuvent ponctuellement limiter cette violence.<ref>Thomas Hobbes, ''Léviathan'', op. cit., chap. XXX, p. 382-389.</ref> == 4. Locke : l’état de nature comme liberté régie par la loi naturelle == John Locke (1632-1704) reprend le langage de l’état de nature, mais en le transformant profondément. Dans le ''Second traité du gouvernement civil'' (1690), l’état de nature est défini comme un « état de parfaite liberté » où les hommes peuvent disposer d’eux-mêmes et de leurs biens sans dépendre de la volonté d’autrui, et comme un état d’égalité où nul n’a, par nature, autorité sur un autre.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. II, § 4-6, p. 18-21.</ref> Cet état de parfaite liberté n’est pas pour autant un état de licence. Il est régi par une loi de nature, que Locke identifie à la raison, et qui prescrit à chacun de conserver sa propre vie, mais aussi celle d’autrui ; nul n’a le droit d’attenter à la vie, à la liberté ou aux biens d’un autre. Dans l’état de nature, chacun est autorisé à punir celui qui enfreint cette loi, de manière proportionnée, afin de réparer le tort et d’empêcher de futures violations.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. II, § 6-11, p. 20-26.</ref> Locke se distingue de Hobbes en séparant nettement l’état de nature et l’état de guerre. L’état de nature est un état de paix possible, où des relations de coopération (famille, échanges, promesses) peuvent exister, tandis que l’état de guerre apparaît seulement lorsqu’un individu use de violence injuste, en s’attaquant à la vie ou aux biens d’un autre.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. III, § 16-21, p. 27-32.</ref> Pourquoi alors quitter l’état de nature ? Parce que, malgré la loi de nature, cette condition comporte de graves « inconvénients » : chacun étant à la fois juge et exécuteur dans sa propre cause, les conflits risquent de dégénérer en spirale de représailles. Il n’existe ni juge impartial, ni force commune pour faire respecter les décisions. De plus, la propriété, que Locke fonde sur le travail, reste vulnérable à la convoitise d’autrui.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. V, § 25-51, p. 73-99.</ref> L’institution d’un pouvoir politique vise donc à garantir la protection des droits naturels – la vie, la liberté, la propriété – en confiant à un gouvernement la fonction de juger et de punir selon des lois publiques. Cependant, l’état civil ne dissout pas les droits naturels : ceux-ci préexistent à l’État et en limitent la légitimité. Si le gouvernement abuse de sa puissance, viole les droits des citoyens ou pervertit la fin pour laquelle il a été institué, le peuple recouvre le droit de résister et, en dernière instance, de se révolter.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. XIX, § 222-243, p. 274-298.</ref> De plus, Locke note que l’état de nature subsiste là où il n’existe pas de pouvoir commun, par exemple dans les relations entre États souverains. == 5. Rousseau : l’état de nature comme hypothèse critique de la société == Jean-Jacques Rousseau (1712-1778) reprend le vocabulaire de l’état de nature pour mieux le détourner. Dans le ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'' (1755), il ne prétend pas retracer historiquement les premiers temps de l’humanité ; il affirme au contraire que ces débuts nous sont inaccessibles et que toute description en est nécessairement hypothétique. L’état de nature est chez lui une fiction méthodique, destinée à dépouiller l’homme de tout ce qu’il doit à la société, à la culture et à la technique, afin de dégager ce qu’il y a de proprement naturel en lui.<ref>Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', op. cit., préface, p. 41-50.</ref> Rousseau s’oppose ainsi au jusnaturalisme classique, qui attribuait à la « nature humaine » des qualités déjà socialisées (raison développée, langage, passions complexes). Il propose de remonter en deçà de ces acquisitions, vers un homme solitaire, robuste, peu sujet à la réflexion, mû principalement par l’amour de soi (souci de sa propre conservation) et par la pitié (répugnance naturelle à voir souffrir ses semblables). Dans cet état, les hommes se croisent rarement ; ils connaissent peu de besoins artificiels, ne dépendent pas les uns des autres, et l’inégalité y est « à peine sensible » et sans effets sociaux durables.<ref>Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', op. cit., première partie, p. 89-115.</ref> L’état de nature, chez Rousseau, est donc relativement paisible et non guerrier. La violence et la domination apparaissent avec le développement de la société : appropriation des terres, division du travail, naissance de la propriété privée, formation de corps politiques inégaux. Le célèbre passage où Rousseau imagine le premier homme ayant enclos un terrain et déclaré « ceci est à moi » marque, dans le ''Discours'', le moment fictif où l’inégalité institutionnelle commence.<ref>Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', op. cit., seconde partie, p. 141-143.</ref> L’état civil n’est pas simplement un remède aux maux de la nature : il est aussi le lieu où ces maux se constituent. Cette analyse négative de la société ne conduit pas Rousseau à prôner un retour à l’état de nature, qu’il juge impossible et absurde. Elle nourrit plutôt une critique des institutions existantes et prépare la réflexion du ''Contrat social'', où il s’agit de concevoir une forme d’association politique qui permette à chacun d’obéir à la loi tout en ne dépendant que de lui-même, en tant que citoyen.<ref>Jean-Jacques Rousseau, ''Du contrat social'', livre I, chap. VI-VIII, éd. Bruno Bernardi, Paris, GF Flammarion, 2002, p. 69-88.</ref> La fiction de l’état de nature devient alors le point de départ d’une reconstruction normative : montrer comment les hommes pourraient instituer un ordre politique où la liberté et l’égalité, perdues dans l’histoire réelle, seraient retrouvées sous une forme nouvelle. == 6. Autres élaborations modernes : Pufendorf, Spinoza, Kant == === 6.1. Pufendorf : un état de nature précaire mais non guerrier === Samuel von Pufendorf (1632-1694), dans ''De jure naturae et gentium'', occupe une position intermédiaire entre Hobbes et Locke. Il admet que l’état de nature est un état d’égalité où nul n’a autorité naturelle sur autrui, mais il insiste sur la « sociabilité » (''socialitas'') comme inclination fondamentale de l’homme.<ref>Samuel von Pufendorf, ''Du droit de la nature et des gens'', op. cit., livre II, chap. III, p. 119-134.</ref> L’état de nature n’est pas pour lui un état de guerre permanente, mais un état de vulnérabilité, où l’absence d’autorité rend l’observation du droit naturel incertaine et les conflits difficiles à régler. Pufendorf en conclut que, bien que la société ne soit pas « naturelle » au sens strict, les hommes ont le devoir moral de sortir de l’état de nature et de fonder un corps politique afin de stabiliser les droits et d’assurer la coopération. La notion d’état de nature sert ainsi à justifier l’État comme condition d’effectivité du droit naturel. === 6.2. Spinoza : continuité entre état de nature et état civil === Chez Spinoza (1632-1677), la distinction entre ''status naturalis'' et ''status civilis'' est centrale, mais elle prend un sens particulier. Dans le ''Traité théologico-politique'' et le ''Traité politique'', Spinoza définit le droit de nature comme la puissance même de l’individu : chacun a par nature le droit de faire tout ce que sa puissance lui permet. L’état de nature est alors la situation où cette puissance individuelle n’est pas encore coordonnée par une institution commune ; chacun y décide, selon son avantage propre, de ce qui est bon ou mauvais.<ref>Baruch Spinoza, ''Traité politique'', op. cit., chap. II, § 4-9, p. 80-88.</ref> Cependant, Spinoza insiste sur le fait que l’état civil ne supprime pas le droit naturel, mais le transforme. Dans l’État bien constitué, le droit de nature n’est plus celui de l’individu isolé, mais celui de la multitude coordonnée « comme par une seule âme » ; le droit de l’État est ainsi le droit naturel même, déterminé par la puissance commune.<ref>Baruch Spinoza, ''Traité politique'', op. cit., chap. III, § 1-3, p. 92-96.</ref> La frontière entre état de nature et état civil est moins une rupture qu’un changement de forme de la puissance. Même dans l’État, certains droits – par exemple la liberté de penser – demeurent inaliénables et ne peuvent être transférés au souverain.<ref>Baruch Spinoza, ''Traité théologico-politique'', chap. XX, trad. Jacqueline Lagrée, Paris, Vrin, 1999, p. 292-305.</ref> L’état de nature conserve ainsi, chez Spinoza, une fonction critique : il rappelle que toute norme juridique repose ultimement sur des rapports de puissance et que le droit ne consiste pas en un ensemble de règles au-dessus de la nature, mais en une modalité de la puissance naturelle elle-même. === 6.3. Kant : l’état de nature comme état d’injustice à dépasser === Immanuel Kant (1724-1804), dans la ''Doctrine du droit'' (première partie de la ''Métaphysique des mœurs'', 1797), reprend la terminologie de l’état de nature, mais en lui conférant un sens strictement juridique. L’« état de nature » n’est pas chez lui un état primitif de barbarie : c’est toute situation où les rapports entre individus ne sont pas régis par des lois publiques et un pouvoir commun. Un tel état est, par définition, un « état d’injustice », non parce que les hommes y seraient nécessairement mauvais, mais parce que le droit de chacun n’y est pas objectivement garanti.<ref>Immanuel Kant, ''Doctrine du droit'', op. cit., § 42-44, p. 130-140.</ref> Kant en tire une thèse célèbre : « sortir de l’état de nature est un devoir ». La raison pratique commande que les hommes instituent un ordre civil où ce qui est « mien » et « tien » soit déterminé selon des lois publiques, sous l’autorité d’un pouvoir législatif commun. De ce point de vue, l’état de nature n’est qu’un état de droit « provisoire », toujours susceptible de devenir injuste, tandis que l’état civil est un état de droit « péremptoire », véritablement contraignant pour tous.<ref>Immanuel Kant, ''Doctrine du droit'', op. cit., § 47, p. 145-148.</ref> Kant étend cette analyse aux relations internationales : entre États souverains, il existe aussi un état de nature, puisque aucun pouvoir supérieur ne peut trancher les conflits ; cet état est lui-même un état d’injustice. D’où l’idée d’un « état juridique cosmopolitique » à atteindre, non pas sous la forme d’un État mondial, mais d’une fédération de peuples engagés vers la paix perpétuelle.<ref>Immanuel Kant, ''Vers la paix perpétuelle'', trad. Alexis Philonenko, Paris, Vrin, 1991, deuxième section, p. 73-104.</ref> == 7. Fonctions philosophiques et enjeux critiques de l’état de nature == On peut dégager plusieurs grandes fonctions philosophiques du concept d’état de nature. Il joue d’abord un rôle de fondation : en décrivant ce que seraient les rapports humains sans institutions, les philosophes cherchent à dégager les conditions de possibilité de toute vie sociale stable et à justifier la nécessité d’un pouvoir politique. Chez Hobbes et Kant, c’est la violence ou l’injustice de l’état de nature qui fonde la légitimité du passage à l’état civil. Chez Locke et Pufendorf, ce sont les inconvénients et l’insécurité de la condition naturelle qui rendent souhaitable et raisonnable l’institution de l’État.<ref>Brian Tierney, ''The Idea of Natural Rights: Studies on Natural Rights, Natural Law, and Church Law, 1150-1625'', Grand Rapids, Eerdmans, 1997, p. 291-326.</ref> L’état de nature remplit ensuite une fonction normative : il sert à définir les droits que les individus possèdent indépendamment de tout pouvoir constitué. Chez Locke, les droits naturels à la vie, à la liberté et à la propriété précèdent l’État et en limitent l’autorité ; l’état civil n’est légitime que s’il protège plus efficacement ces droits que l’état de nature.<ref>John Locke, ''Traité du gouvernement civil'', op. cit., chap. IX, § 123-131, p. 179-188.</ref> Chez Rousseau, à l’inverse, l’état de nature sert à montrer que de nombreuses inégalités tenues pour naturelles ne le sont pas, et que l’ordre social actuel est historiquement produit et donc susceptible d’être transformé.<ref>Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', op. cit., seconde partie, p. 135-165.</ref> Enfin, l’état de nature a une fonction critique. Les anthropologues contemporains, à commencer par Marshall Sahlins, ont montré que la vision hobbesienne de la vie « sauvage » comme brutale et misérable projette sur les sociétés de chasseurs-cueilleurs des catégories issues de la société marchande moderne. Dans ''Stone Age Economics'', Sahlins soutient que bien des sociétés de chasseurs-cueilleurs peuvent être qualifiées d’« sociétés d’abondance originelle », où les besoins sont relativement limités et la coopération plus stable qu’on ne le croit, ce qui remet en cause l’idée d’un état de nature intrinsèquement misérable.<ref>Marshall Sahlins, ''Stone Age Economics'', Chicago, Aldine–Atherton, 1972, chap. 1 : « The Original Affluent Society », p. 1-39.</ref> De même, les historiens des idées ont insisté sur le caractère construit et contextuel des récits de l’état de nature. Des études comme celles de Quentin Skinner ou de Pasquale Pasquino ont montré que la description hobbesienne de l’état de nature est largement informée par l’expérience de la guerre civile anglaise et par les conflits religieux de son temps.<ref>Quentin Skinner, ''Visions of Politics'', vol. 3 : ''Hobbes and Civil Science'', Cambridge, Cambridge University Press, 2002, chap. 4, p. 241-272 ; Pasquale Pasquino, art. cité, p. 197-215.</ref> Loin d’être une représentation neutre de ce que serait l’homme « en soi », l’état de nature cristallise des choix théoriques et politiques : la manière dont on imagine les hommes sans État prépare et justifie la manière dont on conçoit l’État lui-même. Ces critiques n’abolissent pas l’intérêt du concept, mais invitent à le traiter comme une construction argumentative plutôt que comme un fait. Elles conduisent certains auteurs contemporains (par exemple Rawls, avec la « position originelle ») à remplacer l’image de l’état de nature par d’autres dispositifs hypothétiques, jugés plus transparents quant à leurs présupposés et moins chargés de connotations historiques ou ethnocentriques.<ref>John Rawls, ''Théorie de la justice'', trad. Catherine Audard, Paris, Seuil, 1987, § 20-30, p. 143-214.</ref> == 8. Conclusion == L’état de nature est un concept-charnière de la philosophie politique moderne. Qu’il soit pensé comme guerre généralisée (Hobbes), comme liberté égale régie par la loi de nature (Locke), comme hypothèse anthropologique critique (Rousseau), comme puissance naturelle (Spinoza) ou comme état d’injustice à dépasser (Kant), il permet de poser, sous des formes différentes, les mêmes questions fondamentales : qu’est-ce qui fonde la légitimité de l’État ? Quels droits les individus possèdent-ils indépendamment de toute institution ? Pourquoi et à quelles conditions est-il rationnel et juste de renoncer à l’indépendance naturelle pour entrer dans un ordre civil ? En ce sens, l’état de nature n’est pas seulement une fiction du passé, mais un instrument toujours disponible pour interroger les rapports entre liberté individuelle, violence, droit et souveraineté. == Notes et références == {{references|colonnes=2}} == Bibliographie == ; Textes classiques : Thomas Hobbes, ''Léviathan : traité de la matière, de la forme et du pouvoir de la république ecclésiastique et civile'', trad. et notes par François Tricaud, Paris, Sirey, 1971. : John Locke, ''Traité du gouvernement civil'', trad. David Mazel, éd. et introduction de Simone Goyard-Fabre, Paris, GF Flammarion, 1992. : Jean-Jacques Rousseau, ''Discours sur l’origine et les fondements de l’inégalité parmi les hommes'', éd. Blaise Bachofen et Bruno Bernardi, Paris, GF Flammarion, 2008. : Samuel von Pufendorf, ''Du droit de la nature et des gens'', trad. Jean-Louis Thireau, Paris, Vrin, 1993. : Baruch Spinoza, ''Traité politique'', trad. Charles Ramond, Paris, PUF, coll. « Quadrige », 2005. : Immanuel Kant, ''Doctrine du droit'', dans ''La Métaphysique des mœurs'', trad. Alexis Philonenko, Paris, Vrin, 1971. ; Études et commentaires : Marshall Sahlins, ''Stone Age Economics'', Chicago, Aldine–Atherton, 1972. : Quentin Skinner, ''Reason and Rhetoric in the Philosophy of Hobbes'', Cambridge, Cambridge University Press, 1996. : Quentin Skinner, ''Visions of Politics'', vol. 3 : ''Hobbes and Civil Science'', Cambridge, Cambridge University Press, 2002. : Pasquale Pasquino, « Thomas Hobbes : la condition naturelle de l’humanité », ''Revue française de science politique'', vol. 44, n{{o}} 2, 1994, p. 197-215. : Brian Tierney, ''The Idea of Natural Rights: Studies on Natural Rights, Natural Law, and Church Law, 1150-1625'', Grand Rapids, Eerdmans, 1997. : Anthony Pagden, ''The Fall of Natural Man: The American Indian and the Origins of Comparative Ethnology'', Cambridge, Cambridge University Press, 1982. : John Rawls, ''Théorie de la justice'', trad. Catherine Audard, Paris, Seuil, 1987. {{autocat}} qy2x7jefg3ynwrhfis8ul59wdyrvwj8 Dictionnaire de philosophie/Euthanasie 0 83146 768461 754113 2026-06-24T03:17:03Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768461 wikitext text/x-wiki {{DicoPhilo|Euthanasie|lecture=oui}} L'euthanasie, du grec ancien εὐθανασία (''euthanasía'' : εὖ « bonne », θάνατος « mort »), désigne étymologiquement la « bonne mort » ou la « mort douce ». Dans son acception contemporaine, elle renvoie à une pratique — action ou omission — visant à provoquer le décès d'une personne, généralement par un médecin ou sous sa responsabilité, dans le but de mettre fin à des souffrances physiques ou psychologiques jugées intolérables et sans perspective de guérison<ref>Encyclopédie philosophique en ligne, article « Euthanasie », 2014.</ref>. La notion d'euthanasie traverse plusieurs millénaires de réflexion philosophique. Elle demeure l'un des débats les plus intenses en éthique médicale et bioéthique contemporaine, soulevant des questions fondamentales : sur la valeur et le caractère sacré de la vie humaine, les limites de l'autonomie individuelle, la signification de la dignité, et les frontières légitimes de l'intervention médicale. == Histoire et étymologie du concept == === L'Antiquité grecque : mort naturelle et mort philosophique === Dans l'Antiquité gréco-romaine, le terme « euthanasie » qualifiait d'abord un type de mort, celle survenue sans douleur excessive au terme d'une existence bien remplie<ref>Polybe, ''Histoires'', VIII, 34, décrit l'euthanasie comme « l'accomplissement des hommes vertueux ».</ref>. Il s'agissait moins d'une pratique que d'un idéal : mourir paisiblement, en ayant accompli ses devoirs, après avoir laissé une progéniture. Le contexte culturel gréco-romain valorisait une certaine forme de maîtrise face à la mort, mais d'une manière très différente des conceptions modernes. La pensée d'Épicure offre un contraste instructif. Épicure enseigne que la mort n'est pas un mal pour celui qui meurt : « Quand nous existons, la mort n'est pas présente ; quand la mort est présente, nous n'existons pas »<ref>Épicure, ''Lettre à Ménécée'', fragment conservé par Diogène Laërce, ''Vies et doctrines des philosophes illustres'', X, 124-125.</ref>. Cette argumentation vise à libérer l'esprit de l'angoisse thanatophobique, non à justifier le suicide. Pour Épicure, c'est la crainte irraisonnée de la mort qui crée la souffrance, non la mort elle-même. Les Stoïciens, notamment Sénèque et Marc Aurèle, adoptent une position plus nuancée. Ils considèrent que seule la vertu constitue un bien véritable, tandis que la vie, la santé et le plaisir sont des « indifférents préférables » mais non des biens absolus<ref>Sénèque, ''Lettres à Lucilius'', lettre 70, développe cette doctrine des indifférents.</ref>. Cette hiérarchie éthique n'implique pas une apologie du suicide, mais elle ouvre la possibilité théorique qu'une vie vécue dans le vice soit pire que la mort. Sénèque écrit : « Pourquoi vivrais-je, si ma vie m'apparaît infamante ? »<ref>Sénèque, ''Lettres à Lucilius'', lettre 58.</ref> Platon, dans le ''Phédon'', rapporte que Socrate refuse de s'évader et boit la ciguë en restant maître de lui-même, transformant sa mort en acte philosophique<ref>Platon, ''Phédon'', 117b-118b. Socrate demande l'eau rituelle pour les libations, montrant que sa mort est un acte réfléchi et accepté.</ref>. Pourtant, Platon lui-même, ailleurs dans le ''Phédon'', condamne le suicide. Il utilise l'analogie de l'esclave : de même qu'un esclave n'a pas le droit de disposer de sa vie qui appartient à son maître, l'homme ne possède pas sa propre vie mais en est le gardien pour les dieux<ref>Platon, ''Phédon'', 62b-c. Cette argumentation aura une fortune remarquable dans la tradition chrétienne et kantienne.</ref>. Aristote, quant à lui, qualifie le suicide d'acte lâche dans l'''Éthique à Nicomaque''. Il n'y développe pas une théorie complète du suicide, mais sa brève remarque selon laquelle « le suicidé agit lâchement » connaîtra une très longue postérité<ref>Aristote, ''Éthique à Nicomaque'', Livre III, chapitre 7, 1115b32-1116a3.</ref>. Pour Aristote, ceux qui se tuent pour fuir la souffrance ou le malheur agissent en cowards — non par courage. === La Renaissance et la médicalisation du concept === Un tournant majeur s'opère à la Renaissance avec Thomas More. Dans son ''Utopie'' (1516), More imagine une société où les hôpitaux offrent aux malades atteints de maladies incurables et souffrant d'atroces douleurs la possibilité de recevoir des drogues pour mourir sans agonie<ref>Thomas More, ''Utopie'' (1516), Livre II. More écrit : « Comme on les persuade que, puisque la vie leur est devenue un tourment, ils ne doivent pas hésiter à mourir. » Il est important de noter que More décrit cette pratique sans l'endosser personnellement.</ref>. C'est la première apparition du concept d'euthanasie dans un contexte explicitement médical. Francis Bacon poursuit cette réflexion en affirmant que soulager la souffrance du mourant, y compris par l'anticipation de la mort, appartient légitimement à l'art médical. Bacon distingue l'euthanasie (mort bonne et facile) des simples cures médicales, et la place au cœur de la mission du médecin<ref>Francis Bacon, ''The Advancement of Learning'' (1605), Livre IV, chapitre 2. Bacon affirme que la médecine comporte trois objectifs : préserver la santé, guérir les maladies, et « soulager les extrémités des malades, non seulement en prolongeant la vie, mais en adoucissant les douleurs ».</ref>. Cette redéfinition du concept a des conséquences philosophiques importantes. L'euthanasie devient progressivement une question d'éthique médicale plutôt qu'une question de sagesse personnelle face à la mort. Elle se place sous l'autorité du médecin et de l'État, non seulement sous celle de l'individu. === La perversion eugéniste et les crimes nazis === Le XIXe siècle voit une dérive grave du concept. L'euthanasie devient un instrument idéologique au service de l'eugénisme. Elle ne désigne plus la « bonne mort » du malade souffrant, mais l'élimination supposément « douce » de populations jugées défectueuses, dégénérées ou inférieures. Cette évolution culmine avec l'Allemagne nazie : le programme T4 (1939-1945) utilise officiellement le terme « euthanasie » pour justifier l'extermination systématique de plus de 250 000 personnes handicapées, malades mentaux et autres groupes socialement marginalisés<ref>Christian Wunderlich, « Euthanasia in Nazi Germany », ''Holocaust and Genocide Studies'', 2009. Le programme T4 fut l'un des précurseurs du génocide des Juifs, testant les protocoles et l'appareil administratif.</ref>. Cette page sombre de l'histoire a profondément marqué le débat contemporain, enracinant une méfiance durable envers toute légalisation de l'euthanasie. Le philosophe et historien Florian Schui note que cette dérive n'était pas accidentelle : elle résultait d'une logique interne du cadre conceptuel eugéniste appliqué aux vulnérables<ref>Florian Schui, « Austerity: The History of a Dangerous Idea » (2014), analyse les origines philosophiques et politiques de l'eugénisme.</ref>. == Distinctions conceptuelles fondamentales == === Euthanasie active et passive : la controverse de la distinction === La distinction entre euthanasie active et euthanasie passive structure longtemps le débat éthique. L'euthanasie passive consiste à s'abstenir d'intervenir ou à cesser un traitement : débrancher un respirateur, arrêter l'alimentation artificielle, refuser une intervention chirurgicale. L'euthanasie active, inversement, désigne une action positive visant à provoquer la mort : injection intraveineuse de substances mortelles, administration de doses massives de médicaments. Le philosophe James Rachels a radicalement contesté la pertinence morale de cette distinction en 1975<ref>James Rachels, « Active and Passive Euthanasia », ''New England Journal of Medicine'', vol. 292, no 2, 1975, p. 78-80.</ref>. Son argument central est simple mais puissant : si l'on a jugé préférable pour le patient qu'il meure, la distinction morale entre le tuer et le laisser mourir n'est qu'une illusion. Pire, l'euthanasie passive peut prolonger inutilement l'agonie. Rachels illustre son propos par un exemple classique : deux hommes convoitent l'héritage d'un enfant. Le premier le noie dans la baignoire (action). Le second le trouve qui commence à se noyer et le laisse faire (omission). Rachels soutient qu'il n'existe aucune différence morale significative entre ces deux actes — les deux sont également répréhensibles. Philippa Foot répond en défendant la pertinence de la distinction, en s'appuyant sur une éthique des vertus d'inspiration aristotélicienne<ref>Philippa Foot, « Euthanasia », ''Philosophy & Public Affairs'', vol. 6, no 2, 1977, p. 97-120.</ref>. Pour Foot, il existe une différence morale entre violer un droit négatif (le droit de ne pas être tué) et laisser inassouvie une obligation positive (l'obligation de sauver). Elle souligne que cette distinction n'a rien de magique : elle s'inscrit dans une conception des devoirs moraux selon laquelle nous ne sommes pas tenus de faire le bien de toutes les façons possibles, mais seulement d'éviter de faire le mal. La distinction agir/s'abstenir reflète donc une compréhension plus profonde de la responsabilité morale. Le débat entre Rachels et Foot demeure non résolu. Il révèle une tension entre deux intuitions : d'un côté, l'idée que seules les conséquences importent moralement (perspective utilitariste) ; de l'autre, l'idée que la manière dont on produit ces conséquences — les moyens employés — possède une valeur morale propre (perspective déontologique). === Euthanasie directe et indirecte : la doctrine du double effet === Une seconde distinction croise la première. L'euthanasie peut être directe (la mort est le but visé) ou indirecte (la mort est un effet secondaire toléré, mais non recherché). Cette distinction s'enracine dans la doctrine thomiste du double effet, remontant à Thomas d'Aquin<ref>Thomas d'Aquin, ''Somme théologique'', Secunda Secundae, Question 64, Article 7. La doctrine du double effet concerne spécifiquement la légitime défense et l'homicide accidentel.</ref>. La doctrine du double effet énonce que certains actes produisant des conséquences bonnes et mauvaises peuvent être moralement justifiés à condition que quatre critères soient réunis : (1) l'acte lui-même doit être bon ou moralement neutre ; (2) l'intention du sujet doit viser le bon effet, non le mauvais ; (3) le bon effet ne doit pas résulter du mauvais effet, mais tous deux du même acte ; (4) le bon effet doit surpeser le mauvais<ref>Elizabeth Anscombe reformule cette doctrine dans ''L'Intention'' (1957). Elle montre que l'intention morale n'est pas une affaire de psychologie mentale, mais est inscrite dans l'action elle-même.</ref>. En contexte médical, cette doctrine distingue l'administration de morphine à haute dose pour soulager la douleur — même si cela risque d'abréger la vie — de l'injection intraveineuse de potassium ayant pour but explicite de tuer. Dans le premier cas, la mort n'est que prévisible et tolérable, non directement visée. Dans le second, la mort est l'objectif même. Cette distinction s'avère pratiquement cruciale pour les législations sur la fin de vie. En France, par exemple, la sédation profonde et continue est légale si l'intention est manifestement de soulager et non de tuer, quand bien même l'accélération de la mort serait un effet connu<ref>Loi Claeys-Leonetti du 2 février 2016 en France. La loi autorise « la sédation profonde et continue » maintenue jusqu'au décès « si elle est proportionnée aux circonstances et si elle constitue le seul recours pour éviter une souffrance insupportable ».</ref>. Quelques philosophes contemporains ont cependant remis en question l'utilité morale de cette distinction. Frances Kamm, notamment, soutient que l'intention n'est pas moralement déterminante si elle ne fait aucune différence dans les faits ou dans les résultats<ref>Frances Kamm, « Physician-Assisted Suicide, the Doctrine of Double Effect, and the Ground of Value », ''Ethics'', vol. 109, no 3, 1999, p. 586-607.</ref>. Kamm argumente que ce qui compte moralement, c'est de bien comprendre la causalité entre l'action et ses effets, pas uniquement l'état mental du médecin. === Euthanasie volontaire, non volontaire, involontaire === La dernière distinction fondamentale porte sur le consentement. L'euthanasie volontaire repose sur une demande explicite, répétée et éclairée du patient. L'euthanasie non volontaire concerne ceux qui ne peuvent consentir : patients dans le coma, nouveau-nés gravement malformés, personnes atteintes de démence avancée. L'euthanasie involontaire, enfin, désigne l'élimination délibérée de quelqu'un capable de donner son consentement mais qui n'a pas été consulté ou qui refuse explicitement. Cette classification s'avère éthiquement cruciale. L'euthanasie involontaire est universellement condamnée comme du meurtre. L'euthanasie volontaire soulève un débat éthique profond où l'autonomie individuelle joue un rôle central. L'euthanasie non volontaire pose les questions les plus délicates : comment déterminer l'intérêt véritable d'une personne incapable de s'exprimer ? Qui décide ? Sur quelles bases<ref>Peter Singer, ''Practical Ethics'' (3e éd., 2011), distingue clairement ces trois formes et n'accorde pas le même statut moral à chacune.</ref> ? == Grandes approches philosophiques == === La perspective déontologique : Kant et la dignité inviolable === Emmanuel Kant pose l'une des objections les plus fortes au suicide et à l'euthanasie. Dans les ''Fondements de la métaphysique des mœurs'' (1785), Kant argumente que le suicide repose sur une contradiction performative de la volonté. Le sujet qui se tue par amour de soi — pour échapper à la misère — se contredit : « L'amour de moi-même qui m'incite à me procurer une vie heureuse m'oblige à maintenir cette vie »<ref>Emmanuel Kant, ''Fondements de la métaphysique des mœurs'' (1785), trad. V. Delbos, Paris, Delagrave, 1980, p. 96-97.</ref>. Comment puis-je user du principe de l'amour de moi-même pour détruire moi-même ? Plus fondamentalement encore, Kant invoque l'impératif catégorique sous sa formulation humaniste : « Agis de telle sorte que tu traites l'humanité aussi bien dans ta personne que dans celle de tout autre toujours en même temps comme une fin, et jamais simplement comme un moyen »<ref>Emmanuel Kant, ''Fondements de la métaphysique des mœurs'', Deuxième section.</ref>. Le suicide traite la personne humaine — l'agent lui-même — comme un simple moyen. Le sujet suicidaire se réduit à un instrument servant à fuir la souffrance. Cela viole l'absolu du respect dû à la dignité rationnelle. Cette position kantienne a inspiré des objections vigoureuses au suicide assisté dans le droit contemporain. Mais elle a aussi suscité des réinterprétations créatives. Certains penseurs, à l'instar de David Velleman, soutiennent que continuer à vivre quand on ne peut plus exercer son autonomie rationnelle — quand on est réduit à un simple corps souffrant sans conscience — peut aussi violer la dignité kantienne<ref>David Velleman, « A Right of Self-Termination? », ''Ethics'', vol. 109, no 4, 1999, p. 606-628.</ref>. La personne rationnelle que j'ai été exigerait-elle que je continue à exister en tant que coquille vide ? D'autres philosophes kantiens, comme Norbert Campagna, contestent cet argument : pour Kant, la dignité réside précisément dans notre caractère de fin en soi, indépendamment de nos capacités actuelles. Un patient en coma possède toujours la dignité d'une personne rationnelle, même s'il ne peut exercer aucune capacité rationnelle<ref>Norbert Campagna, ''Kant and the Human Dignity'', Springer, 2007.</ref>. === L'utilitarisme : maximiser le bien-être et minimiser la souffrance === L'utilitarisme, fondé par Jeremy Bentham et raffiné par John Stuart Mill, évalue la moralité selon les conséquences. Est bon ce qui produit « le plus grand bonheur du plus grand nombre ». Le calcul utilitariste appliqué à l'euthanasie aboutit à une conclusion prima facie favorable : si un patient en phase terminale endure des douleurs atroces sans espoir d'amélioration, et si prolonger sa vie produit davantage de souffrance que de bien-être, alors l'euthanasie augmente l'utilité globale<ref>Bentham, ''Introduction to the Principles of Morals and Legislation'' (1789).</ref>. Peter Singer, l'utilitariste contemporain le plus influent, défend l'euthanasie volontaire sur cette base. Pour Singer, il est difficile de justifier pourquoi empêcher quelqu'un de mourir quand il le demande et que cette mort améliorerait clairement son sort<ref>Peter Singer, « Voluntary Euthanasia: A Utilitarian Perspective », ''Bioethics'', vol. 17, no 5-6, 2003, p. 475-502.</ref>. L'interdiction de l'euthanasie volontaire prolonge simplement la souffrance d'êtres conscients qui ne désirent plus vivre. Cependant, l'utilitarisme peut mener à des conclusions morales contre-intuitives et potentiellement dangereuses. Si ce qui compte est uniquement le solde de bien-être, pourquoi ne pas éliminer une personne en état végétatif permanent qui ne connaît aucune joie mais impose un fardeau au système de santé ? Un utilitariste naïf serait contraint d'accepter cette conclusion. Singer répond en développant une version sophistiquée : l'utilitarisme des préférences<ref>Singer, ''Practical Ethics'' (3e éd., 2011).</ref>. Ce qui compte ne sont pas seulement les états de conscience, mais les préférences autonomes des individus. Respecter qu'une personne ait la préférence de vivre, même si objectivement sa vie contient peu de plaisir, est moralement important. Reste une difficulté majeure : les conséquences sociales de la légalisation. Si l'euthanasie est autorisée, des personnes vulnérables — les pauvres, les handicapés, les personnes âgées isolées — subiront-elles des pressions sociales ou économiques pour « choisir » de mourir ? Le philosophe John Hardwig pose la question de manière vertigineuse : existe-t-il un devoir de mourir lorsque poursuivre sa vie impose un fardeau énorme aux proches<ref>John Hardwig, « Is There a Duty to Die? », ''Hastings Center Report'', vol. 27, no 2, 1997, p. 34-42.</ref> ? Même si Hardwig ne prône pas cette position, sa seule formulation met au jour les dérives potentielles de la logique utilitariste appliquée à la vie et la mort. === L'existentialisme et la phénoménologie : l'authenticité face à la mort === Hans Jonas, disciple de Heidegger et philosophe de la responsabilité, propose une perspective existentielle radicale. Pour Jonas, le « droit de mourir » signifie d'abord le droit de refuser un traitement qui prolonge artificiellement l'existence biologique au-delà de ce qui est humainement acceptable<ref>Hans Jonas, « Le droit de mourir », dans ''Technique, médecine et éthique'', trad. française, Paris, Cerf, 1990, p. 49-81.</ref>. La mort est constitutive de notre condition existentielle. L'acharnement thérapeutique moderne, qui transforme la mort en processus techniquement maîtrisable mais existentiellement aliéné, viole notre capacité à « posséder notre propre mort ». Jonas écrit : « Que la mort soit mortelle, c'est sa contradiction première, mais cela fait partie de son essence »<ref>Hans Jonas, ibid., p. 60.</ref>. Nous ne pouvons imaginer la vie autrement que comme mortelle. Vouloir la prolonger indéfiniment par des techniques, c'est nier l'essence même de la condition vivante. Le « droit de mourir » chez Jonas n'est donc pas le droit à l'euthanasie active, mais le droit élémentaire de garder une certaine autonomie existentielle face à la médecine, le droit de dire : « Assez, laissez-moi mourir ». Paul Ricœur, autre penseur existentialiste français, refuse deux attitudes erronées face à la fin de vie : d'une part l'acharnement thérapeutique (qui nie notre mortalité et fuit l'exigence de faire le deuil) ; d'autre part l'euthanasie active (qui exprime une « suprématie » illusoire sur notre propre condition de vulnérabilité)<ref>Paul Ricœur, ''Vivant jusqu'à la mort'', Paris, Seuil, 2007.</ref>. Ricœur soutient que les décisions éthiques face à la mort doivent accepter « l'irréductible tragique » de la condition humaine. Il n'existe pas de solution idéale, seulement des choix entre des « maux » inévitables. Pour Ricœur, cette acceptation du tragique — ce renoncement à la maîtrise totale — est précisément ce qui préserve la dignité humaine contre l'utopie de la toute-puissance<ref>Ricœur, « Point de vue : Paul Ricœur et la fin de vie », entretien dans ''Ouest-France'', 2018.</ref>. Le législateur ne saurait donner sa caution à l'euthanasie, car cela revient à sanctionner institutionnellement une illusion : celle que nous avons le droit de surmonter complètement les limites de notre condition mortelle. === L'éthique du care et les perspectives féministes === L'éthique du care, développée notamment par Carol Gilligan et Nel Noddings, conteste l'accent mis par les théories libérales classiques sur l'autonomie abstraite et désincarnée<ref>Carol Gilligan, ''Une voix différente'' (1982), trad. française, Paris, Flammarion, 2008 ; Nel Noddings, ''Caring: A Feminine Approach to Ethics and Moral Education'', Berkeley, University of California Press, 1984.</ref>. Cette éthique insiste sur le caractère inévitablement relationnel et contextuel de nos vies. Nous ne sommes jamais simplement des individus autonomes rationnels, mais toujours des êtres insérés dans des réseaux de dépendance, de soin et de vulnérabilité. Appliquée à la fin de vie, l'éthique du care suggère que les décisions d'euthanasie ne peuvent être conçues comme l'exercice solitaire d'un droit subjectif. Elles s'inscrivent dans des relations complexes : liens familiaux, responsabilités mutuelles, charge émotionnelle pour les proches. Une décision d'euthanasie volontaire authentique doit tenir compte de ces dimensions relationnelles et ne peut pas être simplement réduite à un choix individuel. Certaines féministes, notamment Susan Wolf, expriment des réticences face à la légalisation de l'euthanasie<ref>Susan Wolf, « Gender, Feminism, and Death: Physician-Assisted Suicide and Euthanasia », dans ''Feminism and Bioethics: Beyond Reproduction'', Oxford University Press, 1996, p. 282-317.</ref>. Elles craignent que l'accent mis sur le droit à l'euthanasie ne reproduise des rapports de genre inégaux. Les femmes, historiquement assignées aux rôles de soignantes, pourraient subir des pressions — explicites ou implicites — pour demander l'euthanasie afin de « ne pas être un fardeau » pour leur famille. De plus, légaliser l'euthanasie pourrait consolider l'idée que certaines vies — celles marquées par la dépendance physique, la vulnérabilité — ne valent pas la peine d'être vécues. D'autres féministes, comme Jennifer Parks, offrent une perspective plus nuancée : une véritable éthique du care exige d'écouter authentiquement les demandes et les besoins de la personne soignée, y compris son souhait de mourir<ref>Jennifer Parks, « Feminist Perspectives on Assisted Dying in Context », dans ''Ethics of Assisted Suicide and Euthanasia'', 2023.</ref>. Interdire l'euthanasie au nom du soin reviendrait à adopter un paternalisme qui nie l'agentivité relationnelle de la personne malade. L'enjeu devient alors de concevoir des cadres légaux qui protègent effectivement les vulnérables tout en respectant leur autodétermination en contexte relationnel. == Enjeux contemporains == === La tension entre dignité subjective et dignité objective === Le mot « dignité » apparaît dans presque tous les débats sur l'euthanasie, mais son sens est profondément contesté. Pour certains, la dignité humaine est un attribut inaliénable et inconditionnel : elle ne dépend pas de l'état de conscience, de santé, ou de capacité rationnelle actuelle. Cette conception découle de traditions religieuses et de la philosophie du droit naturel<ref>John Finnis, ''Natural Law and Natural Rights'', Oxford University Press, 1980 ; voir aussi « Euthanasia, Morality, and Law », ''Loyola of Los Angeles Law Review'', vol. 31, 1998, p. 1123-1145.</ref>. Si tout être humain possède une dignité égale et inaliénable, alors accepter l'euthanasie revient à juger que certaines vies humaines ne méritent pas d'être vécues — ce qui violerait le principe fondamental d'égalité morale. Pour d'autres penseurs, notamment des libéraux conséquentialistes, la dignité réside précisément dans l'autonomie : dans la capacité d'autodétermination rationnelle. Ronald Dworkin développe cette perspective dans ''Life's Dominion''<ref>Ronald Dworkin, ''Life's Dominion: An Argument about Abortion, Euthanasia, and Individual Freedom'', New York, Knopf, 1993.</ref>. Dworkin affirme qu'interdire l'euthanasie volontaire à quelqu'un qui souffre atrocement et en demande explicitement la fin représente « une forme odieuse de tyrannie » qui viole le droit à l'autodétermination. Respecter la dignité d'une personne signifie respecter sa vision du bien et de la vie digne. Cette tension entre deux conceptions irréconciliables de la dignité reflète un désaccord fondamental sur l'anthropologie morale : sommes-nous en premier lieu des êtres possesseurs de droits inaliénables (vision objective), ou des agents autonomes capables de définir notre propre conception du bien et du monde (vision subjective) ? === Les expériences légales : leçons des Pays-Bas et de la Belgique === Les Pays-Bas et la Belgique offrent les expériences législatives les plus anciennes et les plus documentées. Les Pays-Bas ont formellement légalisé l'euthanasie et le suicide assisté par médecin le 1ᵉʳ avril 2002, bien que la pratique fût toléréement régulée depuis les années 1980<ref>''Termination of Life on Request and Assisted Suicide (Review Procedures) Act'', Pays-Bas, 2002.</ref>. La loi n'établit pas un « droit à l'euthanasie », mais plutôt une exonération de responsabilité pénale pour les médecins qui respectent des critères de diligence stricts. Ces critères sont : (1) la demande du patient doit être volontaire, persévérante et bien réfléchie ; (2) la souffrance doit être physique ou psychologique, insupportable, et sans perspective d'amélioration ; (3) le patient doit être pleinement informé de son état et des alternatives ; (4) il ne doit exister aucune autre solution raisonnable ; (5) un second médecin indépendant doit être consulté ; (6) l'acte doit être réalisé avec soin professionnel<ref>Les critères sont énumérés dans la loi et développés par les commissions régionales d'examen (RTE).</ref>. Chaque cas doit être rapporté à une commission régionale qui vérifie a posteriori le respect des critères. La Belgique légalise l'euthanasie trois mois après les Pays-Bas, le 28 mai 2002<ref>Loi belge relative à l'euthanasie, 28 mai 2002, entrée en vigueur en septembre 2002.</ref>. La loi belge présente des différences importantes : elle ne dépénalise pas l'euthanasie au sens strict (qui reste théoriquement un crime, mais le médecin qui suit la procédure n'est pas poursuivi) ; elle exige la consultation de l'équipe soignante ; elle institue une procédure renforcée pour les patients non en phase terminale. En 2014, la Belgique étend l'accès aux mineurs sans limite d'âge, à condition que l'enfant ait « la capacité de discernement »<ref>Amendement à la loi belge sur l'euthanasie, 10 février 2014. Cette extension suscita une controverse internationale intense.</ref>. Les données empiriques révèlent une augmentation progressive du nombre d'euthanasies depuis la légalisation. Aux Pays-Bas, environ 8 % des décès (5 200 cas en 2021) résultent d'euthanasie ; en Belgique, le chiffre est autour de 4-5 %<ref>Gouvernement néerlandais, rapport annuel sur l'euthanasie, 2021 ; Commission fédérale de contrôle et d'évaluation de l'euthanasie, rapport annuel en Belgique, 2021.</ref>. Le taux de déclaration s'est amélioré : autour de 80 % aux Pays-Bas, mais demeure plus faible en Belgique (environ 50-53 %)<ref>Penney Lewis et Isra Black, « The Effectiveness of Legal Safeguards in Jurisdictions that Allow Assisted Dying », Nuffield Foundation Briefing Paper, 2012.</ref>. === Les dérives redoutées : le problème de la pente glissante === L'un des arguments majeurs contre la légalisation est l'argument de la pente glissante (« slippery slope »). Il existe deux versions de cet argument. La version empirique soutient que, même avec des safeguards stricts, la légalisation mènera inévitablement à des dérives et à des abus : élargissement des critères d'éligibilité, euthanasies non volontaires, pressions sur les personnes vulnérables<ref>L'archevêque Anthony Fisher développe cet argument empirique dans son débat avec Peter Singer, 2018.</ref>. La version logique affirme que les principes justifiant l'euthanasie volontaire (autonomie, qualité de vie subjective) conduisent logiquement à justifier aussi l'euthanasie non volontaire ou involontaire, si on applique les mêmes critères de manière cohérente. L'expérience néerlandaise et belge fournit des éléments de réponse nuancés. D'un côté, les données montrent bien un élargissement des critères. Aux Pays-Bas, des cas d'euthanasie pour « souffrance existentielle » (sans maladie physique terminale) ont été approuvés ; des euthanasies de patients atteints de démence avancée ont eu lieu ; récemment, certains cas impliquaient des personnes atteintes de troubles psychiatriques<ref>Des euthanasies pour « unbearable suffering » sans diagnostic de maladie terminale ont été acceptées aux Pays-Bas. Voir rapport de 2016.</ref>. De l'autre côté, ces élargissements se sont produits dans un cadre procédural et n'ont pas débouché sur un chaos moral. L'euthanasie involontaire demeure fortement stigmatisée et extrêmement rare, pratiquement inexistante dans les chiffres officiels. Cependant, des critiques persistent. Penney Lewis pointe que le système de contrôle est principalement rétrospectif, ce qui limite son efficacité preventive<ref>Penney Lewis, « Assisted Dying: European Approaches and the Need for Regulation », Oxford Journal of Legal Studies, 2014.</ref>. Si un médecin viole les critères, le pire qui peut arriver est de ne pas être poursuivi si le dossier est approuvé ; s'il est rejeté, les poursuites peuvent intervenir, mais tard, après les faits. D'autre part, le taux de déclaration incomplet (surtout en Belgique) signifie que des cas problématiques peuvent échapper entièrement aux commissions de contrôle. Enfin, certains observateurs soulèvent la question de la « normalisation » : à mesure que l'euthanasie devient légale et régulée, elle cesse d'être perçue comme une exception dramatique pour devenir une simple option parmi d'autres. Cela risque de transformer les attentes sociales envers les personnes âgées, malades, ou handicapées — qui pourraient finir par se sentir obligées de « choisir » la mort pour ne pas être un poids<ref>Cette inquiétude est exprimée par plusieurs anthropologues et sociologues travaillant sur la fin de vie. Voir Schuklenk et Smajdor, 2011.</ref>. === La question de la vulnérabilité et de la protection === Un enjeu crucial concerne la protection des personnes vulnérables. Même si légalement l'euthanasie exige le consentement explicite, certains groupes — les pauvres, les personnes handicapées, celles victimes de précarité sociale — sont particulièrement exposés à des pressions subtiles. Une personne isolée, sans famille aisée pour l'aider, pourrait subir des pressions indirectes (coût des traitements, manque de personnel soignant, sentiment de culpabilité) pour demander l'euthanasie. Susan Wolf développe cette critique : l'autonomie libérale est une fiction abstraite qui occulte les conditions sociales réelles de la prise de décision<ref>Susan Wolf, « Gender, Feminism, and Death », op. cit.</ref>. Les femmes, particulièrement les femmes âgées et les femmes de couleur dans les contextes nord-américains, connaissent systématiquement moins d'accès aux ressources de soin. Pour elles, l'« autonomie » de choisir la mort s'exerce dans un contexte fortement contraint par les inégalités. D'autres critiques soulèvent le problème économique crûment : dans un système de santé rationalisé et déjà saturé, n'existe-t-il pas un incitatif économique silencieux à favoriser l'euthanasie des patients les plus coûteux (les personnes très âgées, polyhandicapées, en phase terminale prolongée) ? Le Canada a controversiellement étendu l'aide à mourir aux personnes ayant uniquement des difficultés économiques<ref>Canada élargit l'accès à l'aide à mourir médicale. À partir de mars 2024, les personnes dont le seul problème médical est une « difficulté économique » peuvent y accéder. Cette décision a suscité une controverse mondiale.</ref>, ce qui semblerait confirmer les craintes des penseurs critiques. === L'euthanasie non volontaire === Une difficulté particulière porte sur l'euthanasie non volontaire : comment décider pour ceux qui ne peuvent s'exprimer ? C'est le cas des nouveau-nés gravement malformés, des patients en état végétatif permanent, des personnes atteintes de démence avancée. Plusieurs approches philosophiques se proposent de répondre. L'approche du « meilleur intérêt » (« best interests ») affirme que les décisions doivent servir l'intérêt de la personne incapable, même si elle ne peut l'exprimer. Mais qu'est-ce que l'intérêt véritable d'un nouveau-né sans conscience, sans famille, gravement malformé ? Y a-t-il un « bénéfice » à prolonger une existence sans possibilité d'expérience positive<ref>Cette question est au cœur du débat sur les nouveau-nés extrêmement prématurés ou gravement malformés.</ref> ? L'approche du « substituted judgment » (« décision substituée ») affirme que le tuteur légal doit se demander ce que le patient aurait voulu s'il avait pu s'exprimer. Mais cette approche suppose qu'on peut connaître les préférences hypothétiques de quelqu'un qui ne les a jamais formulées et qui peut ne jamais avoir eu la capacité rationnelle de les formuler. Ces questions éthiques restent extrêmement difficiles, et les différentes juridictions y répondent de manières divergentes. Certaines interdisent entièrement l'euthanasie non volontaire (États-Unis, Royaume-Uni). D'autres l'autorisent dans des cas extrêmes strictement encadrés (Pays-Bas, Belgique). Une médiane consiste à autoriser l'arrêt ou le retrait de traitements extraordinaires (respirateur, alimentation artificielle) mais pas l'administration active de substances mortelles. == Conclusion == Le débat philosophique sur l'euthanasie cristallise les tensions les plus profondes de l'éthique contemporaine. Il oppose des visions irréconciliables de la personne humaine : l'une insistant sur la dignité inaliénable et inconditionnelle, l'autre sur l'autonomie et l'autodétermination. Il met en tension le respect de l'individu et la protection des vulnérables. Il demande comment concilier le pluralisme moral — le fait que les citoyens d'une société libérale désacordent profondément sur le bien et le mal — avec l'existence d'une loi commune. Les données en provenance des juridictions qui ont légalisé l'euthanasie offrent des leçons ambiguës. Elles montrent qu'il est techniquement possible d'encadrer la pratique par des procédures rigoureuses et de maintenir une certaine discipline morale. Mais elles révèlent aussi que les frontières entre « cas appropriés » et « dérives » se déplacent avec le temps, sous la pression de demandes individuelles nouvelles et de changements sociaux. Plus profondément, le débat sur l'euthanasie force la philosophie à affronter ce qui pourrait s'appeler le « tragique de la condition humaine finie ». Nous sommes des êtres mortels, vulnérables, dépendants, qui aspirons aussi à l'autonomie et à la dignité. Aucune solution législative ne peut surmonter complètement cette tension. Les Pays-Bas et la Belgique n'ont pas « résolu » le problème de l'euthanasie : ils ont instauré une régulation pragmatique d'une pratique que la pure logique morale laisserait peut-être insoluble. Les réponses que chaque société apporte à la question « devrions-nous légaliser l'euthanasie ? » révèlent les priorités morales et anthropologiques qui définissent cette société. Elles constituent moins des jugements définitifs que des expériences éthiques réversibles et révisables. == Notes et références == {{references}} == Références bibliographiques == * Anscombe, Elizabeth, ''L'Intention'', trad. M. Michaux, Paris, Gallimard, 2002 [1957]. * Aristote, ''Éthique à Nicomaque'', trad. J. Tricot, Paris, Vrin, 1987. * Bacon, Francis, ''The Advancement of Learning'', 1605. * Beauchamp, Tom et Childress, James, ''Principles of Biomedical Ethics'', Oxford University Press, 8e éd., 2013. * Benatar, David, ''Better Never to Have Been: The Harm of Coming into Existence'', Oxford University Press, 2006. * Campagna, Norbert, ''Kant and the Human Dignity'', Springer, 2007. * Dworkin, Ronald, ''Life's Dominion: An Argument about Abortion, Euthanasia, and Individual Freedom'', New York, Knopf, 1993. * Finnis, John, ''Natural Law and Natural Rights'', Oxford University Press, 1980. * Finnis, John, « Euthanasia, Morality, and Law », ''Loyola of Los Angeles Law Review'', vol. 31, 1998, p. 1123–1145. * Foot, Philippa, « Euthanasia », ''Philosophy & Public Affairs'', vol. 6, no 2, 1977, p. 97–120. * Foot, Philippa, « The Problem of Abortion and the Doctrine of the Double Effect », ''Oxford Review'', no 5, 1967. * Gilligan, Carol, ''Une voix différente. Pour une éthique du care'', trad. A. Kwiatek, Paris, Flammarion, 2008 [1982]. * Hardwig, John, « Is There a Duty to Die? », ''Hastings Center Report'', vol. 27, no 2, 1997, p. 34–42. * Jonas, Hans, ''Le Principe responsabilité. Une éthique pour la civilisation technologique'', trad. J. Greisch, Paris, Cerf, 1990 [1979]. * Jonas, Hans, « Le droit de mourir », dans ''Technique, médecine et éthique'', trad. française, Paris, Cerf, 1990 [1985], p. 49–81. * Kamm, Frances M., « Physician-Assisted Suicide, the Doctrine of Double Effect, and the Ground of Value », ''Ethics'', vol. 109, no 3, 1999, p. 586–607. * Kant, Emmanuel, ''Fondements de la métaphysique des mœurs'', trad. V. Delbos, Paris, Delagrave, 1980 [1785]. * Lewis, Penney et Black, Isra, « The Effectiveness of Legal Safeguards in Jurisdictions that Allow Assisted Dying », Nuffield Foundation Briefing Paper, janvier 2012. * Lewis, Penney, « Assisted Dying: European Approaches and the Need for Regulation », ''Oxford Journal of Legal Studies'', vol. 34, no 3, 2014, p. 499–529. * Mill, John Stuart, ''De la liberté'', trad. L. Lenglet, Paris, Gallimard, 1990 [1859]. * Mill, John Stuart, ''L'Utilitarisme'', trad. G. Tanesse, Paris, Flammarion, 1988 [1861]. * More, Thomas, ''L'Utopie'', trad. M. Delcourt, Paris, Flammarion, 1987 [1516]. * Noddings, Nel, ''Caring: A Feminine Approach to Ethics and Moral Education'', Berkeley, University of California Press, 1984. * Parks, Jennifer, « Feminist Perspectives on Assisted Dying in Context », dans ''Ethics of Assisted Suicide and Euthanasia'', 2023. * Platon, ''Phédon'', trad. M. Dixsaut, Paris, Flammarion, 1991. * Rachels, James, « Active and Passive Euthanasia », ''New England Journal of Medicine'', vol. 292, no 2, 1975, p. 78–80. * Ricœur, Paul, ''Vivant jusqu'à la mort, suivi de Fragments'', Paris, Seuil, Points Essais, 2018 [2007]. * Schui, Florian, ''Austerity: The History of a Dangerous Idea'', Oxford University Press, 2014. * Sénèque, ''Lettres à Lucilius'', trad. H. Noblot, Paris, Les Belles Lettres, 1989. * Singer, Peter, ''Practical Ethics'', 3e éd., Cambridge University Press, 2011. * Singer, Peter, « Voluntary Euthanasia: A Utilitarian Perspective », ''Bioethics'', vol. 17, no 5-6, 2003, p. 475–502. * Thomas d'Aquin, ''Somme théologique'', trad. A.-M. Roguet, Paris, Cerf, 1984. * Velleman, David H., « A Right of Self-Termination? », ''Ethics'', vol. 109, no 4, 1999, p. 606–628. * Wolf, Susan, « Gender, Feminism, and Death: Physician-Assisted Suicide and Euthanasia », dans Susan Wolf (dir.), ''Feminism and Bioethics: Beyond Reproduction'', Oxford University Press, 1996, p. 282–317. == Voir aussi == *{{Page|Bioéthique}} *{{Page|Suicide}} *{{Page|Autonomie}} *{{Page|Utilitarisme}} *{{Page|Déontologie}} *{{Page|Mort}} {{AutoCat}} 3xp85cluy4c3q3dh7h6ylwdskr46r9l Dictionnaire de philosophie/Existence 0 83174 768462 767902 2026-06-24T03:17:13Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768462 wikitext text/x-wiki {{DicoPhilo|Existence|lecture=oui}} L'existence constitue l'une des notions fondamentales de la philosophie, désignant le fait d'être, de se tenir dans la réalité. Du latin ''ex-sistere'' (« se tenir hors de », « sortir de »), le terme renvoie à la présence effective dans le monde, par opposition à l'essence qui définit ce qu'une chose est. Cette distinction entre existence et essence traverse toute l'histoire de la philosophie occidentale et a donné lieu à des débats qui se poursuivent jusqu'à aujourd'hui. == Émergence médiévale du concept == Le concept d'existence, au sens philosophique strict, émerge tardivement dans l'histoire de la pensée. Dans l'Antiquité grecque, Platon et Aristote n'emploient pas de terme spécifiquement dédié à ce que nous nommons aujourd'hui « existence ». Aristote parle de l'« être en tant qu'être » (''to on hê on'') dans sa ''Métaphysique'', mais cette notion recouvre l'ensemble de ce qui est, sans séparer nettement existence et essence<ref>Aristote, ''Métaphysique'', Γ, 1, 1003a20-25, traduction J. Tricot, Paris, Vrin, 1991, p. 155-156.</ref>. C'est au Moyen Âge que la notion d'existence acquiert son statut philosophique propre, particulièrement dans le cadre de la pensée arabo-persane et de la scolastique latine. Avicenne (Ibn Sīnā, 980-1037) introduit une distinction capitale entre l'essence (''māhiyya'') et l'existence (''wujūd''). Pour lui, l'existence n'est pas contenue dans l'essence des choses créées : elle leur advient de l'extérieur, par l'acte créateur de Dieu, qui est le seul « Existant nécessaire » (''wājib al-wujūd''), celui en qui essence et existence sont identiques<ref>Avicenne, ''Métaphysique du Shifā'', IX, 4, traduction G. Anawati, Paris, Vrin, 1978, p. 262-263.</ref>. Cette doctrine aura une influence déterminante sur la pensée médiévale occidentale. Thomas d'Aquin (1225-1274) reprend et développe cette distinction dans son traité ''De ente et essentia'' (1254-1256), où il affirme que dans les créatures, l'essence et l'acte d'être (''esse'') sont réellement distincts. L'essence détermine ce qu'une chose est, tandis que l'existence est l'acte par lequel cette essence se tient dans la réalité. Seul Dieu, en tant qu'« acte pur d'exister » (''ipsum esse subsistens''), est tel que son essence consiste à exister<ref>Thomas d'Aquin, ''De ente et essentia'', chapitre IV, édition L.-B. Geiger, Paris, Vrin, 1948, p. 34-35.</ref>. Cette « composition réelle » entre essence et existence dans les êtres créés fonde la métaphysique thomiste de la participation : les créatures participent à l'être divin sans s'identifier à lui<ref>Étienne Gilson, ''L'être et l'essence'', Paris, Vrin, 1948, rééd. 2000, p. 141-162.</ref>. == La critique kantienne : l'existence n'est pas un prédicat réel == La conception médiévale de l'existence comme propriété réelle des choses sera radicalement remise en question par Emmanuel Kant (1724-1804). Dans la ''Critique de la raison pure'' (1781), Kant formule une objection décisive contre la preuve ontologique de l'existence de Dieu, en affirmant que « l'être n'est manifestement pas un prédicat réel, c'est-à-dire un concept de quelque chose qui puisse s'ajouter au concept d'une chose »<ref>Emmanuel Kant, ''Critique de la raison pure'', AK III, 398 (A 598/B 626), traduction A. Tremesaygues et B. Pacaud, Paris, PUF, 1944, rééd. 1968, p. 428.</ref>. Pour Kant, dire qu'une chose existe n'ajoute rien à son concept. L'existence n'est pas une détermination qui enrichirait la compréhension de l'objet, mais désigne seulement « la position absolue de la chose »<ref>Ibid., A 599/B 627, p. 429.</ref>. Un exemple fameux illustre cette thèse : cent thalers réels ne contiennent pas plus de déterminations que cent thalers possibles ; la différence ne réside pas dans le contenu du concept, mais dans le fait que les thalers réels sont posés dans le contexte de l'expérience possible<ref>Ibid., A 599/B 627, p. 429-430.</ref>. L'existence n'est donc pas un attribut de la chose, mais concerne notre rapport cognitif à elle : elle signifie que l'objet est donné dans l'expérience sensible, qu'il appartient au « contexte de toute l'expérience »<ref>Ibid., A 601/B 629, p. 431.</ref>. Cette analyse kantienne aura des conséquences considérables. Elle met fin à la possibilité de déduire l'existence à partir de l'essence, et rejette toute prétention de la métaphysique rationnelle à établir l'existence de Dieu ou de l'âme par la seule analyse conceptuelle. Comme Kant l'affirme lui-même, « notre conscience de toute existence appartient entièrement à l'unité de l'expérience »<ref>Ibid., A 601/B 629, p. 431.</ref>. == Kierkegaard et la subjectivité existante == Au XIXe siècle, Søren Kierkegaard (1813-1855) opère un renversement fondamental en faisant de l'existence non plus un problème logique ou métaphysique, mais une question éminemment subjective et personnelle. Contre le système hégélien qui prétend englober toute la réalité dans le mouvement dialectique de l'Idée, Kierkegaard affirme l'irréductibilité de l'existence individuelle, singulière et contingente. Pour le philosophe danois, l'existence désigne le mode d'être propre à l'individu humain dans sa dimension concrète, temporelle et passionnée. Exister, ce n'est pas simplement « être là », mais se rapporter à soi-même dans l'inquiétude, le choix et l'engagement. « La vérité, c'est la subjectivité », écrit-il dans le ''Post-scriptum aux Miettes philosophiques'' (1846), signifiant par là que la vérité existentielle ne réside pas dans l'objectivité d'un savoir abstrait, mais dans l'appropriation subjective par laquelle l'individu fait sienne une conviction et l'incarne dans sa vie<ref>Søren Kierkegaard, ''Post-scriptum définitif et non scientifique aux Miettes philosophiques'', traduction P.-H. Tisseau, Paris, Gallimard, 1949, p. 197-198.</ref>. Kierkegaard distingue plusieurs « stades » ou « sphères » de l'existence : le stade esthétique, où l'individu vit dans l'instant et la jouissance ; le stade éthique, où il assume la responsabilité de ses choix dans la durée ; et le stade religieux, où il se rapporte à Dieu dans la foi, par-delà toute médiation rationnelle<ref>Søren Kierkegaard, ''Ou bien... ou bien'', traduction F. et O. Prior et M.-H. Guignot, Paris, Gallimard, 1943, tome II, p. 154-186.</ref>. L'existence authentique suppose le passage par l'angoisse, sentiment qui révèle à l'individu sa liberté vertigineuse et la possibilité du péché<ref>Søren Kierkegaard, ''Le Concept de l'angoisse'', traduction K. Ferlov et J.-J. Gateau, Paris, Gallimard, 1935, rééd. 1969, p. 47-61.</ref>. == L'existentialisme sartrien : l'existence précède l'essence == Jean-Paul Sartre (1905-1980) reprend et radicalise l'héritage kierkegaardien en formulant le principe fondamental de l'existentialisme athée : « l'existence précède l'essence »<ref>Jean-Paul Sartre, ''L'existentialisme est un humanisme'', Paris, Nagel, 1946, p. 21-22.</ref>. Cette formule condense une thèse ontologique et anthropologique : l'être humain existe d'abord, surgit dans le monde, et ce n'est qu'ensuite qu'il se définit par ses choix et ses actes. Il n'y a pas de nature humaine préétablie, pas d'essence qui précéderait et déterminerait l'existence, car « il n'y a pas de Dieu pour la concevoir »<ref>Ibid., p. 22.</ref>. Dans ''L'être et le néant'' (1943), Sartre distingue deux modes d'être fondamentaux : l'« en-soi » (''en-soi''), qui caractérise les choses inertes, massives, coïncidant pleinement avec elles-mêmes ; et le « pour-soi » (''pour-soi''), qui définit la conscience humaine comme néantisation, arrachement à soi, perpétuel dépassement vers des possibles<ref>Jean-Paul Sartre, ''L'être et le néant. Essai d'ontologie phénoménologique'', Paris, Gallimard, 1943, rééd. « Tel », 1976, p. 33-34, 111-142.</ref>. Le pour-soi existe sur le mode du « ne pas être ce qu'il est et être ce qu'il n'est pas » : il est toujours en projet, en avance sur lui-même, condamné à la liberté<ref>Ibid., p. 515-516.</ref>. Cette liberté ontologique implique une responsabilité totale : « l'homme est condamné à être libre » et « responsable de ce qu'il est »<ref>Sartre, ''L'existentialisme est un humanisme'', op. cit., p. 37, 24.</ref>. Choisir pour soi, c'est choisir pour toute l'humanité, car en se faisant, l'homme dessine une image de ce que devrait être l'homme<ref>Ibid., p. 25-26.</ref>. De cette structure existentielle découle l'angoisse, sentiment de la liberté face à elle-même, mais aussi la mauvaise foi, attitude par laquelle la conscience tente de fuir sa liberté en se réifiant, en se faisant chose<ref>Sartre, ''L'être et le néant'', op. cit., p. 82-106.</ref>. == Heidegger et la question de l'être : le Dasein == Martin Heidegger (1889-1976) renouvelle profondément la question de l'existence en l'inscrivant dans le cadre d'une interrogation plus originaire : la question du sens de l'être. Dans ''Être et temps'' (''Sein und Zeit'', 1927), Heidegger introduit le concept de « Dasein » (littéralement « être-là ») pour désigner l'être humain en tant qu'il est le lieu où la question de l'être se pose<ref>Martin Heidegger, ''Être et temps'', traduction F. Vezin, Paris, Gallimard, 1986, §2, p. 33-38.</ref>. Le Dasein se distingue de tous les autres étants par le fait que « dans son être, il y va de cet être même » (''in seinem Sein um dieses Sein selbst geht'')<ref>Ibid., §4, p. 53.</ref>. Autrement dit, le Dasein n'est pas simplement présent comme une chose, mais existe : il se rapporte à son être, il a à être. Heidegger réserve le terme « existence » (''Existenz'') au seul Dasein, pour le distinguer de l'« être-sous-la-main » (''Vorhandenheit'') des objets et de l'« être-à-portée-de-main » (''Zuhandenheit'') des ustensiles<ref>Ibid., §9, p. 67-70.</ref>. L'existence du Dasein se caractérise par plusieurs « existentiaux », structures ontologiques fondamentales : l'« être-au-monde » (''In-der-Welt-sein''), qui signifie que le Dasein n'est jamais isolé mais toujours déjà engagé dans un monde familier<ref>Ibid., §12-13, p. 78-92.</ref> ; l'« être-avec » (''Mitsein''), qui indique la coexistence originaire avec autrui<ref>Ibid., §26, p. 156-158.</ref> ; la « préoccupation » (''Sorge''), qui unifie la structure temporelle du Dasein comme être jeté dans un passé, projeté vers des possibles futurs, et présent à son monde<ref>Ibid., §41, p. 237-248.</ref>. Heidegger distingue l'existence authentique (''eigentlich'') de l'existence inauthentique (''uneigentlich''). Le plus souvent, le Dasein vit dans le « On » (''das Man''), mode d'être anonyme où il se conforme aux normes sociales et se perd dans la quotidienneté<ref>Ibid., §27, p. 162-170.</ref>. L'existence authentique, au contraire, suppose que le Dasein assume sa finitude et se rapporte à sa mort comme possibilité ultime, « possibilité de l'impossibilité de l'existence »<ref>Ibid., §53, p. 329-332.</ref>. C'est dans l'angoisse face à la mort que le Dasein accède à sa liberté la plus propre, à sa « résolution devançante » (''vorlaufende Entschlossenheit'')<ref>Ibid., §62, p. 382-387.</ref>. == Perspectives contemporaines == La phénoménologie française du XXe siècle prolonge et transforme l'analyse heideggérienne. Maurice Merleau-Ponty (1908-1961) insiste sur l'ancrage corporel de l'existence : le corps n'est pas un objet parmi d'autres, mais le « véhicule de l'être au monde », le lieu d'insertion dans le tissu du sensible<ref>Maurice Merleau-Ponty, ''Phénoménologie de la perception'', Paris, Gallimard, 1945, rééd. « Tel », 1976, p. 97.</ref>. Exister, c'est d'abord être chair (''Leib''), sentir et être senti, dans une « intentionnalité opérante » qui précède toute activité réflexive<ref>Ibid., p. 478-495.</ref>. Gabriel Marcel (1889-1973), représentant de l'existentialisme chrétien, distingue le « problème » (question objective, extérieure au sujet) du « mystère » (réalité qui englobe le sujet et ne peut être objectivée). L'existence appartient au registre du mystère : je ne peux la traiter de l'extérieur, car « je suis mon corps » et non pas « j'ai un corps »<ref>Gabriel Marcel, ''Être et avoir'', Paris, Aubier, 1935, rééd. 1968, p. 11-29.</ref>. L'existence se révèle dans la « participation » à autrui, dans l'engagement et la fidélité qui constituent des « indices de métaproblématique »<ref>Gabriel Marcel, ''Du refus à l'invocation'', Paris, Gallimard, 1940, p. 47-62.</ref>. Karl Jaspers (1883-1969) élabore une philosophie de l'« Existenz », qu'il distingue du simple « Dasein » (être-là empirique). L'Existenz désigne la liberté propre de l'individu qui se réalise dans les « situations-limites » (''Grenzsituationen'') – mort, souffrance, combat, faute – où il est confronté à des dimensions de l'être qu'aucune connaissance objective ne peut maîtriser<ref>Karl Jaspers, ''Philosophie'', tome II, ''Éclairement de l'existence'', traduction J. Hersch, Berlin, Springer, 1932, rééd. Paris, Springer-Verlag France, 1986, p. 177-230.</ref>. Dans ces situations, l'individu accède à la transcendance et réalise son « être-soi » authentique (''Selbstsein'')<ref>Ibid., p. 231-289.</ref>. == Débats contemporains en ontologie analytique == Dans la tradition analytique anglo-saxonne, la question de l'existence est reprise à nouveaux frais. Après Bertrand Russell et Gottlob Frege, qui ont montré que l'existence est un quantificateur logique et non un prédicat de premier ordre<ref>Gottlob Frege, « Fonction et concept » (1891), dans ''Écrits logiques et philosophiques'', traduction C. Imbert, Paris, Seuil, 1971, p. 97-98.</ref>, des débats importants émergent au XXe siècle sur le statut ontologique des objets non existants. Alexius Meinong (1853-1920) avait défendu l'idée qu'il existe des objets « subsistants » (comme le nombre deux ou l'or) qui n'ont pas d'existence spatio-temporelle, et même des objets « inexistants » (comme le cercle carré) qui possèdent des propriétés sans exister<ref>Alexius Meinong, « Über Gegenstandstheorie » (1904), dans ''Gesamtausgabe'', vol. II, Graz, Akademische Druck, 1971, p. 481-535.</ref>. Cette position, critiquée par Russell, a été reprise sous diverses formes dans les débats contemporains sur la quantification et la référence<ref>William C. Kneale et Martha Kneale, ''The Development of Logic'', Oxford, Clarendon Press, 1962, p. 696-707.</ref>. Willard Van Orman Quine (1908-2000) formule le critère célèbre : « Être, c'est être la valeur d'une variable liée » (''to be is to be the value of a bound variable'')<ref>Willard Van Orman Quine, « On What There Is » (1948), dans ''From a Logical Point of View'', Cambridge (Mass.), Harvard University Press, 1953, rééd. 1980, p. 15.</ref>. Selon ce critère, poser la question de l'existence revient à déterminer sur quelles entités nos théories quantifient. Cette approche déplace la question de l'existence du champ de la métaphysique spéculative vers celui de l'analyse logique du langage et de l'engagement ontologique de nos discours théoriques<ref>Willard Van Orman Quine, ''Le mot et la chose'' (1960), traduction J. Dopp et P. Gochet, Paris, Flammarion, 1977, p. 297-325.</ref>. == Conclusion == La notion d'existence parcourt toute l'histoire de la philosophie occidentale, du questionnement médiéval sur la distinction essence-existence jusqu'aux analyses phénoménologiques et existentialistes du XXe siècle, en passant par la critique kantienne et les développements de l'ontologie analytique. Loin d'être une évidence, l'existence apparaît comme un concept polysémique, susceptible d'acceptions multiples selon qu'on l'envisage du point de vue logique (quantification), métaphysique (acte d'être), épistémologique (position dans l'expérience) ou existentiel (mode d'être du sujet humain). Le débat entre essentialisme et existentialisme, la tension entre objectivité et subjectivité, la question du rapport entre langage et être continuent de structurer la réflexion philosophique contemporaine sur ce qui signifie « être » et « exister ». Comme l'écrivait Heidegger au début d'« Être et temps », « cette question est aujourd'hui tombée dans l'oubli », mais elle demeure « la question fondamentale de la philosophie »<ref>Heidegger, ''Être et temps'', op. cit., §1, p. 27.</ref>. == Notes et références == {{references|colonnes=2}} == Bibliographie sélective == * Aristote, ''Métaphysique'', livres Γ et Z, traduction J. Tricot, Paris, Vrin, 1991. * Thomas d'Aquin, ''De ente et essentia'' / ''L'être et l'essence'', édition bilingue L.-B. Geiger, Paris, Vrin, 1948. * Emmanuel Kant, ''Critique de la raison pure'', traduction A. Tremesaygues et B. Pacaud, Paris, PUF, 1944, rééd. 1968. * Søren Kierkegaard, ''Post-scriptum définitif et non scientifique aux Miettes philosophiques'', traduction P.-H. Tisseau, Paris, Gallimard, 1949. * Martin Heidegger, ''Être et temps'', traduction F. Vezin, Paris, Gallimard, 1986. * Jean-Paul Sartre, ''L'être et le néant. Essai d'ontologie phénoménologique'', Paris, Gallimard, 1943. * Jean-Paul Sartre, ''L'existentialisme est un humanisme'', Paris, Nagel, 1946. * Étienne Gilson, ''L'être et l'essence'', Paris, Vrin, 1948, rééd. 2000. * Frédéric Nef, ''Qu'est-ce que la métaphysique ?'', Paris, Gallimard, 2004. {{autocat}} ok1oyifp14ptf604bzf3c6wimfv4cfl Dictionnaire de philosophie/Expérience de pensée 0 83183 768463 754371 2026-06-24T03:17:23Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768463 wikitext text/x-wiki {{DicoPhilo|Expérience de pensée|lecture=oui}} L'expérience de pensée (en allemand ''Gedankenexperiment'', en anglais ''thought experiment'') constitue une méthode philosophique et scientifique qui consiste à examiner un scénario hypothétique imaginaire dans le but d'explorer les conséquences d'une théorie, d'un principe ou d'un concept<ref>Brown, James Robert, ''The Laboratory of the Mind: Thought Experiments in the Natural Sciences'', 2ᵉ édition, Londres, Routledge, 2011 (1991), p. 1-12</ref>. Contrairement aux expériences empiriques qui manipulent des objets physiques dans des conditions contrôlées, les expériences de pensée se déroulent entièrement dans l'imagination, bien qu'elles puissent avoir des implications décisives pour notre compréhension du monde réel et de nos concepts<ref>Sorensen, Roy A., ''Thought Experiments'', Oxford, Oxford University Press, 1992, p. 205-224</ref>. ==Histoire et terminologie== Le terme ''Gedankenexperiment'' a été employé pour la première fois de manière systématique par le savant et écrivain allemand Georg Christoph Lichtenberg (1742–1799), qui utilise l'expression ''mit Gedanken experimentieren'' dans ses carnets privés (Sudelbücher) à partir de 1764<ref>Georg Christoph Lichtenberg, ''Sudelbücher'', Heft J, édité par Wolfgang Promies, in ''Schriften und Briefe'', vol. 2, Francfort-sur-le-Main, Hanser, 1994 (posthume)</ref>. Cependant, l'usage moderne et formalisé du terme ''Gedankenexperiment'' provient du physicien et philosophe Ernst Mach, qui lui consacre un essai en 1905 intitulé « Über Gedankenexperiment »<ref>Mach, Ernst, « Über Gedankenexperiment », in ''Erkenntnis und Irrtum: Skizzen zur Psychologie der Forschung'', 2ᵉ édition, Leipzig, Johann Ambrosius Barth, 1905, p. 183-199</ref>. Bien que la terminologie soit relativement récente, la méthode elle-même traverse toute l'histoire de la philosophie. Les paradoxes de Zénon d'Élée au cinquième siècle avant notre ère, l'allégorie de la caverne de Platon, ou encore le malin génie de Descartes dans ses ''Méditations métaphysiques'' (1641) constituent autant d'exemples d'expériences de pensée avant la lettre<ref>Rescher, Nicholas, « Thought Experiments in Pre-Socratic Philosophy », in Horowitz, Tamara et Massey, Gerald (dir.), ''Thought Experiments in Science and Philosophy'', Lanham, Rowman & Littlefield, 1991, p. 31-41</ref>. La méthode a joué un rôle crucial dans le développement de la science moderne, notamment chez Galilée et dans la physique du vingtième siècle avec Einstein<ref>Norton, John D., « Thought Experiments in Einstein's Work », in Horowitz, Tamara et Massey, Gerald (dir.), ''Thought Experiments in Science and Philosophy'', Lanham, Rowman & Littlefield, 1991, p. 129-148</ref>. ==Nature et structure== ===Caractéristiques générales=== Une expérience de pensée se distingue par plusieurs traits essentiels. Elle commence par la description d'un scénario hypothétique qui peut être physiquement irréalisable mais qui doit rester conceptuellement cohérent. Ce scénario est ensuite examiné pour en tirer des conclusions concernant la validité d'une théorie, l'applicabilité d'un concept, ou la nature d'un phénomène<ref>Häggqvist, Sören, « A Model for Thought Experiments », ''Canadian Journal of Philosophy'', vol. 39, n° 1, 2009, p. 55-76</ref>. Les expériences de pensée peuvent servir plusieurs fonctions distinctes. Certaines visent à réfuter une théorie en montrant qu'elle conduit à des conséquences absurdes ou contradictoires. D'autres cherchent à soutenir une hypothèse en démontrant sa cohérence ou ses implications fécondes. D'autres encore ont une fonction essentiellement illustrative, rendant accessible et concrète une théorie abstraite<ref>Gendler, Tamar Szabó, ''Thought Experiment: On the Powers and Limits of Imaginary Cases'', New York, Garland Press, 2000, p. 13-42</ref>. ===Le caractère modal=== Les expériences de pensée se caractérisent par leur dimension modale : elles concernent ce qui pourrait être le cas plutôt que ce qui est effectivement le cas. Cette particularité soulève une question épistémologique fondamentale : comment la simple contemplation d'une situation imaginaire peut-elle nous fournir des connaissances authentiques sur le monde réel ou sur nos concepts<ref>Norton, John D., « Why Thought Experiments Do Not Transcend Empiricism », in Hitchcock, Christopher (dir.), ''Contemporary Debates in Philosophy of Science'', Oxford, Blackwell, 2004, p. 44-66</ref> ? Trois types de modalité interviennent dans les expériences de pensée. La modalité des conditions initiales modifiées permet d'examiner ce qui se passerait si certains paramètres étaient différents. La modalité des problèmes modifiés explore des variations dans la formulation même de la question. Enfin, certaines expériences de pensée impliquent une modalité des lois modifiées, envisageant des mondes possibles régis par des principes différents<ref>Butterfield, Jeremy, « Some Aspects of Modality in Analytical Mechanics », in Stadler, Michael (dir.), ''Probability in Physics'', Berlin, Springer, 2004, p. 105-156</ref>. ==Exemples paradigmatiques== ===Les corps en chute libre de Galilée=== L'une des expériences de pensée les plus célèbres est attribuée à Galilée dans ses ''Discorsi e dimostrazioni matematiche intorno a due nuove scienze'' (''Dialogues Concerning Two New Sciences'', 1638). Galilée vise à réfuter la théorie aristotélicienne selon laquelle les corps lourds tombent plus vite que les corps légers. Il imagine deux corps de poids différents attachés ensemble et lâchés d'une certaine hauteur. Si l'on accepte le principe aristotélicien, deux prédictions contradictoires semblent s'ensuivre. D'une part, le corps le plus léger devrait ralentir le corps le plus lourd, de sorte que l'ensemble tomberait à une vitesse intermédiaire entre celles des deux corps séparés. D'autre part, puisque le poids de l'ensemble est supérieur à celui du corps le plus lourd seul, l'ensemble devrait tomber plus vite. La résolution proposée par Galilée consiste à affirmer que tous les corps tombent à la même vitesse (ou plutôt, accélèrent de manière égale), indépendamment de leur poids, car la différence réside dans la résistance de l'air et non dans une propriété intrinsèque de la chute<ref>Galilei, Galileo, ''Discorsi e dimostrazioni matematiche intorno a due nuove scienze'', Leiden, Elsevier, 1638 (traduit sous le titre ''Two New Sciences'', par Stillman Drake, Toronto, Wall & Thompson, 1974, p. 107-109)</ref><ref>Gendler, Tamar Szabó, « Galileo and the Indispensability of Scientific Thought Experiment », ''British Journal for the Philosophy of Science'', vol. 49, n° 3, 1998, p. 397-424</ref>. Cette expérience illustre la fonction réfutative des expériences de pensée : elle démontre qu'une théorie conduit à une contradiction interne lorsqu'on en examine rigoureusement les conséquences. ===Le plan incliné de Stevin=== Simon Stevin (1548-1620), dans son traité de statique ''De Beghinselen der Weeghconst'' (1586), établit le rapport entre la force et l'inclinaison d'un plan sans frottement au moyen d'une expérience de pensée devenue célèbre. Il imagine une chaîne de billes identiques également espacées, suspendue autour d'un prisme triangulaire dont la base est horizontale. Stevin constate que la chaîne doit être en équilibre, car si elle se mettait en mouvement dans une direction, elle continuerait indéfiniment dans un mouvement perpétuel – ce qui lui paraît absurde et constitue une violation du principe de l'impossible mouvement perpétuel. En coupant imaginairement la partie inférieure de la chaîne, qui exerce une force égale des deux côtés, les billes le long des plans inclinés doivent rester en équilibre. Comme le nombre de billes de chaque côté est proportionnel à la longueur du plan, et que les billes ont un poids égal, il en découle que deux corps sur deux plans inclinés différents sont en équilibre si leurs poids sont inversement proportionnels aux sinus de l'angle d'inclinaison (ou proportionnels aux rapports des hauteurs aux longueurs)<ref>Stevin, Simon, ''The Principal Works of Simon Stevin'', vol. 1, édité par Ernst Jan Dijksterhuis, Amsterdam, C. W. Swets and Zeitlinger, 1955 (1586), p. 175-179</ref>. Cette expérience illustre la fonction supportive : elle fournit une justification intuitive à un principe physique en montrant qu'une conclusion alternative conduirait à une situation inacceptable. ===Le train d'Einstein et la relativité de la simultanéité=== Albert Einstein, dans son ouvrage de vulgarisation ''Über die spezielle und die allgemeine Relativitätstheorie'' (''The Meaning of Relativity: The Theory of the Relativity of Gravitation'', 1916), utilise une expérience de pensée pour illustrer la relativité de la simultanéité. Il imagine une personne debout sur le quai d'une voie ferrée et une autre dans un train en mouvement. Deux éclairs frappent le quai en deux points équidistants d'un observateur placé au milieu. Pour l'observateur sur le quai, les deux éclairs sont simultanés : les rayons lumineux émis des deux points l'atteignent au même instant. Mais pour l'observateur dans le train, qui se déplace vers l'un des points et s'éloigne de l'autre, les deux éclairs ne sont pas simultanés. Comme la vitesse de la lumière est constante dans tous les référentiels (principe fondamental de la relativité restreinte), l'éclair vers lequel il se déplace l'atteint avant l'autre. Einstein en conclut que « les événements qui sont simultanés par rapport au quai ne sont pas simultanés par rapport au train, et vice versa »<ref>Einstein, Albert, ''Relativity: The Special and General Theory'', traduit par Robert W. Lawson, New York, Crown Publishers, 1961 (1916), p. 25-30</ref>. Cette expérience a une fonction principalement illustrative : elle rend accessible une conséquence contre-intuitive de la théorie de la relativité restreinte. ===La Terre jumelle de Putnam=== Hilary Putnam propose en 1975 une expérience de pensée qui a profondément influencé la philosophie du langage et de l'esprit. Il demande d'imaginer qu'il existe quelque part dans l'univers une planète, la Terre jumelle, identique en tous points à la Terre, à une exception près : sur la Terre jumelle, le liquide qui remplit les océans et les lacs, qui tombe du ciel et que l'on boit, n'est pas de l'H₂O mais une substance de formule chimique différente, appelons-la XYZ. Ce liquide est perceptuellement indiscernable de l'eau terrestre. Les habitants de la Terre jumelle l'appellent « eau » dans leur langue. Putnam imagine que cette expérience se déroule à une époque où ni les Terriens ni les habitants de la Terre jumelle ne connaissent la composition chimique des liquides respectifs<ref>Putnam, Hilary, « The Meaning of "Meaning" », in ''Mind, Language and Reality: Philosophical Papers, Volume 2'', Cambridge, Cambridge University Press, 1975, p. 215-271</ref>. La question se pose alors : quand un Terrien nommé Oscar et son jumeau sur la Terre jumelle, physiquement et psychologiquement identiques, utilisent le mot « eau », veulent-ils dire la même chose ? Putnam répond que non. Oscar fait référence à l'H₂O, tandis que son jumeau fait référence à XYZ. Cette expérience soutient l'externalisme sémantique, la thèse selon laquelle « les significations ne sont pas dans la tête », mais dépendent de l'environnement du locuteur<ref>Ball, Derek, « Twin-Earth Externalism and Concept Possession », ''The Australasian Journal of Philosophy'', vol. 85, n° 3, 2007, p. 457-472</ref><ref>Farkas, Katalin, « Does Twin Earth Rest on a Mistake? », ''Proceedings of the Aristotelian Society'', vol. 8, n° 2, 2003, p. 135-158</ref>. ===La chambre de Mary et l'argument de la connaissance=== Frank Jackson présente en 1982 une expérience de pensée qui est devenue centrale dans les débats sur la conscience et le physicalisme. Mary est une scientifique brillante spécialisée dans la neurophysiologie de la vision. Elle possède toutes les connaissances physiques concernant la perception des couleurs : elle connaît les longueurs d'onde impliquées, les processus neuronaux, les mécanismes cérébraux du cortex visuel. Mais Mary a toujours vécu dans une chambre en noir et blanc et n'a jamais expérimenté la couleur. Un jour, elle sort de sa chambre et voit pour la première fois quelque chose de rouge<ref>Jackson, Frank, « Epiphenomenal Qualia », ''The Philosophical Quarterly'', vol. 32, n° 127, 1982, p. 127-136</ref>. La question est la suivante : Mary apprend-elle quelque chose de nouveau quand elle voit du rouge pour la première fois ? Jackson soutient que oui : elle fait l'expérience de ce que cela fait de voir du rouge, ce qu'elle ne pouvait pas savoir auparavant malgré toute sa connaissance physique exhaustive. Si Mary apprend quelque chose de nouveau, alors il existe des faits concernant l'expérience consciente qui ne sont pas des faits physiques, ce qui réfute le physicalisme. L'expérience soulève la question des qualia, ces propriétés qualitatives subjectives de l'expérience consciente<ref>Nida-Rümelin, Martine, « Qualia: The Knowledge Argument », ''Stanford Encyclopedia of Philosophy'', édité par Edward N. Zalta, 2002, en ligne</ref><ref>Crane, Tim, « Knowledge Argument and Knowledge », ''Philosophia'', vol. 47, 2019, p. 1811-1824</ref>. ===Le cerveau dans une cuve=== Cette expérience de pensée, popularisée par Hilary Putnam dans ''Reason, Truth and History'' (1981), constitue une version moderne du doute hyperbolique cartésien. Imaginez que vous soyez un cerveau maintenu artificiellement en vie dans une cuve remplie de nutriments. Vos terminaisons nerveuses sont connectées à un ordinateur qui stimule votre cerveau de manière à produire des expériences sensorielles parfaitement cohérentes mais entièrement illusoires. Dans ce scénario, toutes vos croyances concernant le monde extérieur seraient fausses<ref>Putnam, Hilary, ''Reason, Truth and History'', Cambridge, Cambridge University Press, 1981, p. 1-21</ref>. Putnam utilise cette expérience pour développer un argument anti-sceptique fondé sur l'externalisme sémantique. Si nous étions réellement des cerveaux dans une cuve, argue-t-il, nos mots ne pourraient pas faire référence à de vrais cerveaux ou à de vraies cuves, car nous n'aurions jamais eu de contact causal avec de tels objets. Ainsi, l'énoncé « je suis un cerveau dans une cuve » serait nécessairement faux ou dénué de sens. L'argument repose sur une contrainte causale pour la référence : pour qu'un mot réfère à quelque chose, il faut qu'il existe une chaîne causale appropriée entre l'utilisateur du mot et la chose désignée<ref>Müller, Olaf, « Does Putnam's Argument Beg the Question against the Skeptic? », ''Erkenntnis'', vol. 55, n° 3, 2001, p. 357-371</ref><ref>Ludwig, Kirk, « Brains in a Vat, Subjectivity, and the Causal Theory of Reference », ''Journal of Philosophical Research'', vol. 17, 1992, p. 313-345</ref>. ==Enjeux épistémologiques== ===La question du « quoi » : quel type de connaissance ?=== Un débat fondamental porte sur la nature de la connaissance obtenue par les expériences de pensée. Produisent-elles une connaissance nouvelle sur des vérités contingentes du monde naturel, ou révèlent-elles plutôt des vérités nécessaires, conceptuelles ou logiques<ref>Gendler, Tamar Szabó, « Thought Experiments Rethought—and Reperceived », ''Philosophy of Science'', vol. 71, n° 5, 2004, p. 1152-1163</ref> ? On peut soutenir que les expériences de pensée ne fournissent pas, en elles-mêmes, de connaissances nouvelles sur des vérités contingentes. Dans le cas du train d'Einstein, le lecteur n'acquiert pas directement la connaissance empirique que la simultanéité est relative, mais plutôt la connaissance d'une vérité apparemment nécessaire : si la vitesse de la lumière est constante, alors la simultanéité est relative. Cette connaissance conditionnelle peut ensuite être combinée avec la connaissance empirique indépendante que la vitesse de la lumière est effectivement constante. De même, dans l'expérience de Stevin, ce que l'on apprend n'est pas directement le fait contingent concernant la force sur un plan incliné, mais la vérité apparemment nécessaire que si certains états sont des états d'équilibre, alors la force requise obéit à certaines proportions. Cette analyse suggère que les expériences de pensée fonctionnent principalement en rendant explicites les engagements conceptuels ou les conséquences logiques de nos théories et de nos concepts. Elles ne créent pas de connaissances empiriques nouvelles mais réorganisent et clarifient nos connaissances existantes. ===La question du « comment » : quel est le processus cognitif ?=== Un second débat concerne le processus cognitif par lequel les expériences de pensée produisent leurs résultats. Plusieurs positions s'affrontent sur cette question. ====La thèse de l'argumentation==== John D. Norton défend une position empiriste selon laquelle les expériences de pensée ne sont rien d'autre que des arguments ordinaires déguisés sous une forme narrative ou imagée vivante. Sur cette conception, « l'exécution réelle d'une expérience de pensée consiste en l'exécution d'un argument ». Les expériences de pensée ne peuvent donc rien faire de plus, épistémiquement, que l'argumentation ordinaire. La croyance dans le résultat d'une expérience de pensée est justifiée seulement dans la mesure où l'argument reconstruit peut la justifier<ref>Norton, John D., « On Thought Experiments: Is There More to the Argument? », ''Philosophy of Science'', vol. 69, n° 3, 2002, p. 1139-1151</ref><ref>Norton, John D., « Why Thought Experiments Do Not Transcend Empiricism », in Hitchcock, Christopher (dir.), ''Contemporary Debates in Philosophy of Science'', Oxford, Blackwell, 2004, p. 44-66</ref>. Cette position a fait l'objet de nombreuses critiques. Certains objectent que la contemplation de cas imaginaires bien articulés peut donner accès à des informations tacites sur des patterns d'expérience auxquels nous n'avons pas d'accès propositionnel ou conceptuel indépendant<ref>Stuart, Michael T., « Norton and the Logic of Thought Experiments », ''Axiomathes'', vol. 26, n° 4, 2016, p. 451-466</ref>. ====L'approche par modèles mentaux==== Certains philosophes et psychologues cognitifs suggèrent que les expériences de pensée fonctionnent en exploitant les mêmes mécanismes cognitifs que les modèles mentaux. La contemplation d'un scénario imaginaire détaillé activerait des processus quasi-perceptifs qui permettent d'explorer les implications d'une situation de manière similaire, bien que non identique, à l'exploration perceptive d'une situation réelle<ref>Nersessian, Nancy, « In the Theoretician's Laboratory: Thought Experiment as Mental Modeling », ''Proceedings of the Philosophy of Science Association'', vol. 2, 1993, p. 291-301</ref><ref>Miscevic, Nenad, « Mental Models and Thought Experiments », ''International Studies in the Philosophy of Science'', vol. 6, n° 3, 1992, p. 215-226</ref>. Cette approche souligne les similarités entre les expériences de pensée et les expériences réelles. Dans les deux cas, on manipule un système (réel ou imaginaire) et on observe les résultats. Les expériences de pensée peuvent être conçues comme des simulations mentales qui exploitent notre connaissance tacite du monde. ====Le platonisme rationnel==== James Robert Brown défend une position plus audacieuse, selon laquelle certaines expériences de pensée (notamment celle de Galilée) fournissent une connaissance a priori, bien que faillible, de la nature, obtenue par un processus qu'il nomme « intuition platonicienne ». Les expériences de pensée seraient « nos télescopes pour voir le royaume abstrait » et permettraient « de percevoir les lois de la nature a priori en utilisant l'œil de l'esprit ». Ces lois concerneraient des relations nécessaires entre entités abstraites existant objectivement<ref>Brown, James Robert, ''The Laboratory of the Mind: Thought Experiments in the Natural Sciences'', 2ᵉ édition, Londres, Routledge, 2011 (1991), p. 33-75</ref><ref>Brown, James Robert, « Peeking into Plato's Heaven », ''Philosophy of Science'', vol. 71, n° 5, 2004, p. 1126-1138</ref><ref>Grundmann, Thomas, « Platonism and the A Priori in Thought Experiments », in Brown, James Robert, Fehige, Yiftach et Stuart, Michael T. (dir.), ''The Routledge Companion to Thought Experiments'', Londres, Routledge, 2018, p. 195-211</ref>. Cette position, qui présuppose une métaphysique platonicienne et une épistémologie correspondante, demeure minoritaire et controversée. Elle attribue aux expériences de pensée un pouvoir épistémique exceptionnel qui va au-delà de ce que la plupart des philosophes sont disposés à accepter. ====Positions intermédiaires==== Des positions intermédiaires reconnaissent que les expériences de pensée ne sont pas de simples arguments, tout en évitant l'engagement métaphysique du platonisme. Certains soulignent que les expériences de pensée, comme les expériences réelles, manifestent une certaine indifférence à certains types de changements de contenu mais pas à d'autres, ce qui suggère qu'elles ne fonctionnent pas comme de purs arguments<ref>Arthur, Richard, « On Thought Experiments as A Priori Science », ''International Studies in the Philosophy of Science'', vol. 13, n° 3, 1999, p. 215-229</ref><ref>Bishop, Michael, « Why Thought Experiments Are Not Arguments », ''Philosophy of Science'', vol. 66, n° 4, 1999, p. 534-541</ref>. ===Le rôle de l'intuition=== Les expériences de pensée s'appuient largement sur les intuitions qu'elles évoquent. Dans le cas de Galilée, nous avons l'intuition qu'un système ne peut pas prédire deux résultats contradictoires. Dans l'expérience de Stevin, nous avons l'intuition que le mouvement perpétuel est impossible. Ces intuitions jouent un rôle crucial dans la force persuasive des expériences de pensée. Mais d'où proviennent ces intuitions et quelle est leur fiabilité ? Ernst Mach suggère que certaines intuitions résultent d'une « cognition instinctive » accumulée par l'expérience, bien que cette connaissance soit trop peu systématisée pour compter comme connaissance avant l'acte d'imagination dirigée que constitue l'expérience de pensée<ref>Mach, Ernst, ''Knowledge and Error'', traduit par Thomas J. McCormack et Paul Foulkes, Dordrecht, Reidel, 1976 (1905), p. 134-147</ref>. Le développement récent de la « philosophie expérimentale » a conduit à examiner empiriquement les intuitions évoquées par les expériences de pensée philosophiques. Certaines études suggèrent que les intuitions peuvent varier selon les contextes culturels ou les modes de présentation, ce qui soulève des questions sur leur fiabilité comme source de connaissance philosophique<ref>Machery, Edouard et al., « Semantics, Cross-Cultural Style », ''Cognition'', vol. 92, n° 3, 2004, p. B1-B12</ref>. ==Applications et domaines== ===Sciences naturelles=== En physique, les expériences de pensée ont joué un rôle historique crucial. Outre les exemples déjà mentionnés, on peut citer le démon de Maxwell (1867), qui illustre le caractère statistique de la seconde loi de la thermodynamique ; le paradoxe du chat de Schrödinger (1935), qui met en évidence les difficultés d'interprétation de la mécanique quantique<ref>Schrödinger, Erwin, « Die gegenwärtige Situation in der Quantenmechanik », ''Naturwissenschaften'', vol. 23, 1935, p. 807-812, 823-828, 844-849</ref> ; ou encore les paradoxes Einstein-Podolsky-Rosen (1935), qui ont stimulé des décennies de recherche sur l'intrication quantique<ref>Brown, James Robert et Fehige, Yiftach, « Thought Experiments », ''Stanford Encyclopedia of Philosophy'', édité par Edward N. Zalta, 2019, en ligne</ref>. Dans le domaine biologique, les expériences de pensée servent souvent à explorer les implications de la théorie de l'évolution. Darwin lui-même, dans ''L'origine des espèces'' (1859), utilise de nombreux scénarios imaginaires pour montrer comment la sélection naturelle pourrait expliquer divers phénomènes observés. ===Philosophie de l'esprit=== Les expériences de pensée occupent une place centrale dans la philosophie de l'esprit contemporaine. Outre celles de la Terre jumelle, de Mary et du cerveau dans une cuve, on peut mentionner les zombies philosophiques de David Chalmers (1996 – des êtres physiquement identiques à nous mais dépourvus de conscience), l'inversion du spectre (deux personnes ayant des expériences qualitatives inversées pour les mêmes stimuli), ou encore la chambre chinoise de John Searle (1980), qui argue qu'un système purement formel ne peut pas avoir de compréhension authentique du langage<ref>Chalmers, David J., ''The Conscious Mind: In Search of a Fundamental Theory'', Oxford, Oxford University Press, 1996, p. 93-122</ref><ref>Searle, John R., « Minds, Brains, and Programs », ''The Behavioral and Brain Sciences'', vol. 3, n° 3, 1980, p. 417-457</ref>. ===Éthique=== En philosophie morale, les expériences de pensée servent à tester nos intuitions morales et les principes éthiques. Le célèbre « problème du tramway » (trolley problem), formulé par Philippa Foot (1967), puis développé par Judith Jarvis Thomson (1976), demande s'il est permis de tuer une personne pour en sauver cinq. Les variations sur ce problème ont généré une littérature abondante et éclairent les tensions entre différentes théories morales<ref>Foot, Philippa, « The Problem of Abortion and the Doctrine of Double Effect », ''Oxford Review'', n° 5, 1967, p. 5-15</ref><ref>Thomson, Judith Jarvis, « Killing, Letting Die, and the Trolley Problem », ''The Monist'', vol. 59, n° 2, 1976, p. 204-217</ref>. Les expériences de pensée jouent également un rôle important dans les débats sur l'identité personnelle (le bateau de Thésée, les expériences de téléportation), sur le statut moral des animaux et sur la justice distributive (le voile d'ignorance de Rawls). ==Pensées non occidentales et perspectives contemporaines== Bien que la tradition des expériences de pensée soit souvent présentée comme une caractéristique de la philosophie occidentale, d'autres traditions philosophiques ont développé des méthodes apparentées. Dans la philosophie bouddhique, notamment dans les textes du Mādhyamaka, on trouve des raisonnements hypothétiques qui fonctionnent de manière similaire aux expériences de pensée. Les arguments par réduction à l'absurde (prasaṅga) de Nāgārjuna procèdent en montrant que les positions adverses conduisent à des conséquences inacceptables lorsqu'on en examine rigoureusement les implications. Dans la philosophie islamique médiévale, Avicenne (Ibn Sīnā) propose au onzième siècle une expérience de pensée connue sous le nom d'« homme volant » (al-insān al-ṭā'ir). Il demande d'imaginer une personne créée d'un coup dans le vide, sans aucune sensation corporelle. Avicenne soutient que cette personne aurait néanmoins conscience d'elle-même, ce qui démontre que l'âme est une substance indépendante du corps. Cette expérience préfigure des arguments similaires dans la philosophie moderne de l'esprit. Dans la philosophie chinoise, les paradoxes et scénarios hypothétiques abondent, notamment dans les écrits de Zhuangzi (quatrième siècle avant notre ère). Son célèbre rêve du papillon – où il se demande s'il est Zhuangzi ayant rêvé qu'il était un papillon, ou un papillon rêvant qu'il est Zhuangzi – soulève des questions sur l'identité personnelle et la nature de la réalité d'une manière qui rappelle les expériences de pensée occidentales ultérieures. Ces exemples montrent que l'utilisation de scénarios imaginaires pour explorer des questions philosophiques n'est pas l'apanage d'une seule tradition, bien que les contextes théoriques et les objectifs puissent différer. ==Limites et critiques== ===Le problème de la créativité limitée=== L'un des risques des expériences de pensée est qu'elles peuvent être limitées par notre capacité d'imagination. Nous avons tendance à projeter dans les scénarios imaginaires nos préconceptions et nos habitudes de pensée. Ainsi, les expériences de pensée peuvent parfois confirmer nos préjugés plutôt que de les remettre en question. ===La question de la cohérence=== Certains scénarios décrits dans les expériences de pensée peuvent s'avérer, après examen, incohérents ou impossibles de manières que nous n'avions pas anticipées. Par exemple, Daniel Dennett a argumenté que le scénario des zombies philosophiques n'est pas vraiment cohérent, car il suppose possible une séparation entre fonction et phénoménologie qui pourrait être conceptuellement intenable<ref>Dennett, Daniel C., « The Unimagined Preposterousness of Zombies », ''Journal of Consciousness Studies'', vol. 2, n° 4, 1995, p. 322-326</ref>. ===Le risque de pétition de principe=== Les expériences de pensée peuvent parfois présupposer ce qu'elles sont censées démontrer. Les critiques de l'argument du cerveau dans une cuve de Putnam, par exemple, ont souligné que l'argument pourrait commettre une pétition de principe en présupposant l'externalisme sémantique qu'il est censé établir. ===La variabilité des intuitions=== Comme le montrent les travaux en philosophie expérimentale, les intuitions évoquées par les expériences de pensée peuvent varier selon les individus, les cultures ou les contextes de présentation. Cette variabilité soulève des questions sur le statut épistémologique des intuitions comme fondement des arguments philosophiques. ==Conclusion== Les expériences de pensée constituent une méthode philosophique et scientifique d'une richesse remarquable. Elles permettent d'explorer les implications de nos théories, de tester la cohérence de nos concepts et d'éclairer des questions qui ne peuvent pas toujours être abordées par l'expérimentation empirique. Leur force persuasive repose sur leur capacité à rendre vivantes et concrètes des conséquences abstraites, à mobiliser nos intuitions et à révéler des tensions ou des contradictions dans nos systèmes de croyances. Néanmoins, leur statut épistémologique demeure controversé. Le débat entre ceux qui les considèrent comme de simples arguments déguisés et ceux qui leur attribuent un pouvoir cognitif distinct continue d'animer la philosophie contemporaine. Ce débat touche à des questions fondamentales concernant la nature de la connaissance, le rôle de l'imagination dans la cognition et les relations entre le conceptuel et l'empirique. Quelle que soit la position que l'on adopte sur ces questions théoriques, les expériences de pensée demeurent un outil indispensable de la réflexion philosophique et scientifique. Elles nous rappellent que la pensée elle-même, lorsqu'elle est conduite avec rigueur et imagination, peut être une forme d'exploration du réel. ==Notes et références== {{references}} ==Bibliographie== ===Ouvrages généraux=== * Brown, James Robert, ''The Laboratory of the Mind: Thought Experiments in the Natural Sciences'', 2ᵉ édition, Londres, Routledge, 2011 (1991) * Sorensen, Roy A., ''Thought Experiments'', Oxford, Oxford University Press, 1992 * Gendler, Tamar Szabó, ''Thought Experiment: On the Powers and Limits of Imaginary Cases'', New York, Garland Press, 2000 * Horowitz, Tamara et Massey, Gerald (dir.), ''Thought Experiments in Science and Philosophy'', Lanham, Rowman & Littlefield, 1991 * Brown, James Robert, Fehige, Yiftach et Stuart, Michael T. (dir.), ''The Routledge Companion to Thought Experiments'', Londres, Routledge, 2018 ===Études historiques=== * Mach, Ernst, ''Erkenntnis und Irrtum: Skizzen zur Psychologie der Forschung'', 2ᵉ édition, Leipzig, Johann Ambrosius Barth, 1905 * Kuhn, Thomas S., « A Function for Thought Experiments » (1964), in ''The Essential Tension'', Chicago, University of Chicago Press, 1977, p. 240-265 * Rescher, Nicholas, « Thought Experiments in Pre-Socratic Philosophy », in Horowitz, Tamara et Massey, Gerald (dir.), ''Thought Experiments in Science and Philosophy'', Lanham, Rowman & Littlefield, 1991, p. 31-41 ===Études épistémologiques=== * Norton, John D., « Why Thought Experiments Do Not Transcend Empiricism », in Hitchcock, Christopher (dir.), ''Contemporary Debates in Philosophy of Science'', Oxford, Blackwell, 2004, p. 44-66 * Brown, James Robert, « Peeking into Plato's Heaven », ''Philosophy of Science'', vol. 71, n° 5, 2004, p. 1126-1138 * Stuart, Michael T., « The Material Theory of Induction and the Epistemology of Thought Experiments », ''Synthese'', vol. 197, n° 12, 2020, p. 5389-5419 ===Exemples philosophiques=== * Putnam, Hilary, ''Reason, Truth and History'', Cambridge, Cambridge University Press, 1981 * Jackson, Frank, « Epiphenomenal Qualia », ''The Philosophical Quarterly'', vol. 32, n° 127, 1982, p. 127-136 * Chalmers, David J., ''The Conscious Mind: In Search of a Fundamental Theory'', Oxford, Oxford University Press, 1996 ===Ressources en ligne=== * Brown, James Robert et Fehige, Yiftach, « Thought Experiments », ''Stanford Encyclopedia of Philosophy'', édité par Edward N. Zalta, 2019 * Gendler, Tamar Szabó, « Thought Experiments », ''Internet Encyclopedia of Philosophy'', 2013 ==Articles connexes== * Argument * Intuition * Scepticisme * Physicalisme * Imagination [[Catégorie:Épistémologie]] [[Catégorie:Philosophie de l'esprit]] [[Catégorie:Logique]] {{autocat}} sf4nvstwjijzjfe0y71zeswu8p9x7hl Dictionnaire de philosophie/Facticité 0 83203 768464 754696 2026-06-24T03:17:33Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768464 wikitext text/x-wiki Voici une version corrigée et remaniée du texte, avec les imprécisions factuelles rectifiées et le style légèrement resserré. {{DicoPhilo|Facticité|lecture=oui}} La '''facticité''' (du latin ''factum'', « fait », « chose faite ») désigne en philosophie le caractère irréductible des conditions concrètes et contingentes de l'existence humaine. La généalogie moderne du concept se déploie dans le sillage de la philosophie post-kantienne et s'impose, au XX{{e}} siècle, comme une notion centrale de la phénoménologie et de l'existentialisme. Elle oblige à interroger la frontière entre ce qui relève de la nécessité et ce qui procède de la contingence, entre la liberté d'agir et les conditions qui nous sont imposées sans que nous les ayons choisies. === Origines du concept === La réflexion moderne sur la facticité trouve un point de départ décisif dans la ''Critique de la raison pratique'' d'Immanuel Kant (1724-1804). Kant y soutient que la loi morale, en corrélation avec la liberté, est « le seul fait de la raison pure pratique » (''das einzige Faktum der reinen praktischen Vernunft'') : elle ne peut pas être déduite d'un principe plus fondamental et s'impose à nous comme un donné irréductible de la raison elle-même.<ref>Kant, Immanuel, ''Critique de la raison pratique'', traduction François Picavet, Paris, Presses Universitaires de France, coll. « Quadrige », 1943, p. 47.</ref> Le ''factum'' kantien désigne ainsi ce qui se présente à la conscience comme un point de départ que la raison constate sans pouvoir le fonder davantage. Le terme même de ''facticité'' (''Faktizität'') est forgé, dans ce sillage, par Johann Gottlieb Fichte (1762-1814) au tournant du XIX{{e}} siècle, dans le cadre de l'idéalisme transcendantal.<ref>Bruno, G. Anthony, « Facticity and Genesis: Tracking Fichte's Method in the Berlin Wissenschaftslehre », ''Fichte-Studien'', vol. 49, 2021, p. 177-197.</ref> Fichte ne se réfère pas à des faits empiriques isolés, mais au « fait du ''Je pense'' » (''Faktum des Ich denke'') en tant que point de départ irréductible de la philosophie moderne. La facticité nomme ici un point-limite de la réflexion, non pas empirique mais transcendantal : un acte originaire que la pensée ne peut ni dériver ni justifier à partir d'un principe plus fondamental. La facticité ne renvoie donc pas d'abord à la contingence de ce qui arrive, mais à la ''donnée brute'' au sein même de la raison. Des travaux récents ont montré que cette invention fichtéenne du concept de facticité répond à une question post-kantienne décisive : une « science de l'intelligibilité » peut-elle tolérer l'existence de données brutes, irréductiblement non déductibles ?<ref>Bruno, G. Anthony, ''Facticity and the Fate of Reason After Kant'', Oxford, Oxford University Press, 2025.</ref> L'histoire ultérieure du concept de facticité se joue largement autour de cette tension entre l'exigence de rationalité systématique et la reconnaissance de ce qui résiste à la déduction. Au cours du XIX{{e}} siècle, le concept se propage dans la théologie protestante allemande, où il sert à qualifier la facticité des événements constitutifs de l'histoire du salut chrétien, événements sur lesquels la foi vient s'appuyer sans pouvoir les déduire ''a priori''.<ref>Longtin, Ryan A., « Reconsidering Heidegger's Appropriation of Dilthey », ''Continental Philosophy Review'', vol. 54, 2021, p. 371-391.</ref> Wilhelm Dilthey (1833-1911) lui confère une inflexion décisive en l'associant à l'irréductibilité de la vie historique et à tout ce qui demeure inaccessible à une explication conceptuelle pure.<ref>Nelson, Eric Sean, « Empiricism, Facticity, and the Immanence of Life in Dilthey », ''Journal of the British Society for Phenomenology'', vol. 38, n{{o}} 3, 2007, p. 299-313.</ref> La facticité en vient alors à désigner la densité irréductible de la vie vécue, telle qu'elle se sédimente dans l'histoire et les formes de culture. Les néo-kantiens, de leur côté, tracent une distinction nette entre facticité et idéalité : d'une part, le domaine des faits empiriques, de l'autre, celui des normes et des valeurs valant ''a priori''. Cette polarité marquera profondément la philosophie du XX{{e}} siècle, jusque chez Jürgen Habermas qui, dans ''Faktizität und Geltung'' (1992), met explicitement en avant la tension entre la facticité des pratiques juridiques et politiques et la validité normative des principes de droit.<ref>Habermas, Jürgen, ''Droit et démocratie. Entre faits et normes'', traduction Rainer Rochlitz et Christian Bouchindhomme, Paris, Gallimard, 1997.</ref> === Heidegger et l'herméneutique de la facticité === C'est avec Martin Heidegger (1889-1976) que la facticité acquiert sa pleine portée phénoménologique et existentielle. Dès le début des années 1920, lors de son enseignement à l'université de Fribourg, Heidegger élabore une « herméneutique de la facticité » (''Hermeneutik der Faktizität'')<ref>Heidegger, Martin, ''Ontologie. Hermeneutik der Faktizität'' (1923), Gesamtausgabe, vol. 63, Francfort-sur-le-Main, Vittorio Klostermann, 1988 ; trad. fr. Alain Boutot, ''Ontologie. Herméneutique de la facticité'', Paris, Gallimard, 1992.</ref>, qui s'écarte délibérément de la phénoménologie husserlienne de la conscience pure pour se tourner vers la vie en sa facticité quotidienne (''faktisches Leben''). Cette rupture revêt une importance capitale. Selon Heidegger, il ne s'agit plus de dégager des essences idéales en mettant entre parenthèses le monde concret, mais au contraire de partir de la facticité même de l'existence pour en dégager la structure ontologique. La facticité ne désigne pas un simple fait brut ou une donnée empirique sans intérêt philosophique ; elle décrit le mode d'être singulier du ''Dasein'', cet étant que nous sommes chacun. L'être-jeté (''Geworfenheit'') incarne la facticité du ''Dasein''. Ce phénomène fondamental se caractérise par le fait que le ''Dasein'' se découvre toujours déjà situé dans un monde qu'il n'a nullement choisi.<ref>Heidegger, Martin, ''Sein und Zeit'' (1927), Tübingen, Max Niemeyer Verlag, 1967, § 38 ; trad. fr. François Vezin, ''Être et Temps'', Paris, Gallimard, 1986.</ref> Nous n'avons pas décidé de notre naissance, de notre époque, de notre culture, de notre langue, de notre famille. Ces réalités nous constituent sans que nous les ayons préalablement consenties. Heidegger insiste sur le fait que le ''Dasein'' est « jeté » dans l'existence et qu'il ne s'est pas lui-même donné son propre être. Remarquablement, cette facticité de l'être-jeté ne se réduit pas à un événement du passé, comme on situerait une naissance biologique. Elle constitue une dimension permanente de notre existence. Tant que nous existons, nous ne pouvons jamais revenir en deçà de cet être-jeté, jamais le dépasser complètement ou nous en abstraire radicalement.<ref>Warkocki, Witold, ''La notion heideggérienne de facticité dans le contexte de la destruction de l'histoire de l'ontologie'', thèse de doctorat, Université Toulouse-Jean Jaurès, 2019.</ref> La facticité est ainsi une structure ontologique constante, et non un simple obstacle à surmonter. L'être-jeté se manifeste particulièrement dans nos dispositions affectives fondamentales (''Befindlichkeit'' ou ''Stimmung''), ces tonalités émotionnelles qui colorent notre rapport au monde. Que nous soyons anxieux, joyeux, mélancoliques ou irrités, nous habitons ces états affectifs sans vraiment les avoir choisis. L'angoisse (''Angst'') joue un rôle philosophique décisif : elle nous confronte à l'étrangeté (''Unheimlichkeit'') de notre propre existence, à son caractère déroutant et en partie incompréhensible. Dans l'angoisse, le ''Dasein'' éprouve de manière aiguë qu'il n'est pas le maître de son propre fondement, qu'il existe comme un être « qui n'a pas posé lui-même la raison de son être » mais qui doit néanmoins l'assumer et en répondre.<ref>Heidegger, Martin, ''Sein und Zeit'', op. cit., § 40.</ref> L'herméneutique heideggérienne de la facticité s'enracine également dans sa lecture attentive de saint Paul et de l'expérience de la vie chrétienne primitive.<ref>Heidegger, Martin, ''Phänomenologie des religiösen Lebens'' (1920-1921), Gesamtausgabe, vol. 60, Francfort-sur-le-Main, Vittorio Klostermann, 1995 ; trad. fr. Jean Greisch, ''Phénoménologie de la vie religieuse'', Paris, Gallimard, 2011.</ref> Dans ses cours sur la phénoménologie de la vie religieuse, Heidegger analyse l'expérience chrétienne de l'attente de la ''parousie'' (venue du Christ à la fin des temps) telle que l'apôtre Paul la transmet dans la Première épître aux Thessaloniciens. Cette attente transforme chaque instant présent en un ''kairos'', un moment d'urgence et de décision où le chrétien doit demeurer vigilant, car « le jour du Seigneur viendra comme un voleur dans la nuit ».<ref>1 Thessaloniciens 5, 2.</ref> L'inquiétude ontologique produite par l'impossibilité de maîtriser l'avenir tout en devant perpétuellement s'y préparer caractérise, selon Heidegger, la facticité même de l'existence humaine. === Sartre : facticité et transcendance === Jean-Paul Sartre (1905-1980) reprend le concept heideggérien de facticité pour en faire l'une des dimensions fondamentales de ce qu'il appelle la « réalité humaine » dans son ouvrage majeur ''L'Être et le Néant'' (1943).<ref>Sartre, Jean-Paul, ''L'Être et le Néant. Essai d'ontologie phénoménologique'', Paris, Gallimard, coll. « Bibliothèque des Idées », 1943, p. 128.</ref> Pour Sartre, l'existence humaine se caractérise par une tension constitutive et irréductible entre facticité et transcendance. La facticité représente l'ensemble des conditions concrètes et contingentes qui composent le « donné » de notre existence : notre passé irréversible, notre corps avec ses limites et ses capacités, notre situation historique, sociale et culturelle, le lieu de notre naissance, l'environnement matériel qui nous entoure, nos parents, notre classe sociale. Comme Sartre l'exprime avec force, « la facticité est cette contingence perpétuellement évanescente de l'en-soi qui hante le pour-soi ».<ref>Sartre, Jean-Paul, ''L'Être et le Néant'', op. cit., p. 128.</ref> En d'autres termes, tout ce qui en nous possède la modalité opaque et massive de la chose, de l'objet inerte, relève de notre facticité. Cependant, et c'est le point décisif de l'existentialisme sartrien, la réalité humaine ne se réduit jamais à sa seule facticité. Elle est aussi transcendance, c'est-à-dire dépassement perpétuel du donné vers des possibilités futures, projet qui s'arrache constamment à ce qu'il est pour se constituer en ce qu'il n'est pas encore. Sartre fonde sa pensée sur cette thèse fondamentale : « l'existence précède l'essence », ce qui signifie que l'homme existe d'abord, surgit dans le monde comme une contingence absurde, et n'acquiert son essence qu'après coup, à travers ses choix et ses actions.<ref>Sartre, Jean-Paul, ''L'Existentialisme est un humanisme'', Paris, Nagel, 1946, p. 21.</ref> La question se pose alors : la facticité limite-t-elle la liberté ou la constitue-t-elle ? Sartre refuse ces deux positions extrêmes. Il ne s'agit ni d'affirmer que la facticité détermine complètement notre vie, ni de prétendre que nous pouvons nous en abstraire entièrement. Il formule cette exigence dialectique : « Il faut affirmer la facticité comme étant la transcendance et la transcendance comme étant la facticité ».<ref>Sartre, Jean-Paul, ''L'Être et le Néant'', op. cit., p. 124.</ref> Autrement dit, notre liberté ne s'exerce que sur le terrain de notre facticité, et notre facticité ne nous pèse que parce que nous sommes libres de la reprendre ou de la transformer. Nous sommes, selon la formule célèbre de Sartre, « condamnés à être libres », précisément parce que nous ne pouvons pas nous réduire à notre situation, même lorsque nous prétendons le faire. Cette tension entre facticité et transcendance se cristallise dans le phénomène que Sartre nomme la « mauvaise foi », cette attitude par laquelle la conscience tente de fuir l'angoisse vertigineuse de sa propre liberté. La mauvaise foi consiste à nier l'ambiguïté constitutive de la condition humaine : soit en se réduisant à sa facticité pure (en se considérant comme une chose rigidement déterminée), soit en s'évadant dans une fausse transcendance (en niant le poids réel de sa situation).<ref>Sartre, Jean-Paul, ''L'Être et le Néant'', op. cit., première partie, chap. II.</ref> Le garçon de café qui joue mécaniquement son rôle, la femme qui feint d'ignorer les intentions d'un séducteur en abandonnant sa main comme si elle était un objet inerte, illustrent cette fuite devant la complexité ambiguë de l'existence humaine. Selon Sartre, le corps n'est pas un simple objet dans le monde, distinct du sujet pensant. Il constitue notre facticité la plus intime et la plus immédiate. Sartre écrit : « Le corps d'autrui ne doit pas être confondu avec son objectivité. L'objectivité d'autrui est sa transcendance comme transcendée. Le corps est la facticité de cette transcendance. Mais corporéité et objectivité d'autrui sont rigoureusement inséparables. »<ref>Sartre, Jean-Paul, ''L'Être et le Néant'', op. cit., p. 418.</ref> De façon plus large encore, la « situation » rassemble la totalité des coordonnées facticielles qui nous définissent : ma place géographique et sociale, mon passé que je ne peux pas modifier, mon environnement, le prochain dont je dois tenir compte, ma finitude et l'imminence de la mort. Cette situation n'est jamais totalement transparente à ma conscience, et pourtant elle constitue l'horizon dans lequel ma liberté doit nécessairement s'exercer.<ref>Coorebyter, Vincent de, « De la contingence à la situation : dimensions et configurations de la facticité dans ''L'Être et le Néant'' », ''Études sartriennes'', n{{o}} 4, 2000, p. 133-174.</ref> === Simone de Beauvoir et l'ambiguïté existentielle === Simone de Beauvoir (1908-1986) développe une conception originale et décisive de la facticité dans ''Pour une morale de l'ambiguïté'' (1947).<ref>Beauvoir, Simone de, ''Pour une morale de l'ambiguïté'', Paris, Gallimard, 1947, p. 32.</ref> Tandis que Sartre définit la mauvaise foi comme le déni de la dualité qui caractérise l'existence humaine, Beauvoir reformule cette intuition en mettant davantage l'accent sur l'ambiguïté constitutive de toute action concrète. Reconnaître cette ambiguïté, c'est comprendre que nous ne sommes jamais en position de nier ou de transcender complètement nos conditions d'existence. Pour Beauvoir, la facticité n'est nullement ce qui se bornerait à limiter notre liberté ; elle en constitue le matériau indispensable et le terrain concret d'exercice. La liberté ne peut se réaliser que ''dans'' et ''par'' la facticité, en prenant en charge les conditions historiques et sociales de son propre déploiement. C'est dans ce cadre conceptuel qu'elle entreprend son analyse de la condition des femmes dans l'imposant ''Deuxième Sexe'' (1949).<ref>Beauvoir, Simone de, ''Le Deuxième Sexe'', Paris, Gallimard, 1949, t. II, p. 13.</ref> Elle montre comment la facticité biologique (le fait de posséder un corps féminin) se trouve prise dans un réseau de significations sociales et historiques qui constituent une situation d'oppression systématique. Sa formule célèbre — « On ne naît pas femme, on le devient »<ref>Beauvoir, Simone de, ''Le Deuxième Sexe'', op. cit., t. II, p. 13.</ref> — signifie que la facticité corporelle ne détermine pas par elle-même le destin ou l'essence d'un individu : elle est toujours interprétée, investie de sens et vécue dans un contexte culturel spécifique, situé historiquement. Cette thèse de Beauvoir procède d'une interrogation approfondie de la notion sartrienne de situation. Lors de discussions avec Sartre en 1941, elle conteste l'idée selon laquelle la situation serait une pure facticité extérieure dont le sujet libre pourrait s'arracher à volonté. Elle propose les exemples d'une femme musulmane du XVIII{{e}} siècle ou d'une personne réduite en esclavage pour montrer que certaines situations limitent drastiquement, concrètement et matériellement les possibilités réelles de liberté.<ref>Garcia, Manon, « Les ''Mémoires'' comme œuvre philosophique », ''Simone de Beauvoir Studies'', vol. 29, 2018, p. 71-86.</ref> Beauvoir s'oppose ainsi à une conception abstraite et désincarnée de la liberté ; elle insiste sur le fait que la facticité de la situation conditionne réellement et concrètement les possibilités effectives dont dispose un individu donné. === Husserl et le monde de la vie === Edmund Husserl (1859-1938), le fondateur de la phénoménologie transcendantale, n'utilise pas systématiquement le terme de facticité dans son œuvre. Sa réflexion porte néanmoins de façon centrale sur le « monde de la vie » (''Lebenswelt''), cette sphère d'expérience antérieure à toute science, qui constitue le sol sur lequel repose nécessairement toute connaissance.<ref>Husserl, Edmund, ''Die Krisis der europäischen Wissenschaften und die transzendentale Phänomenologie'' (1936), Husserliana, vol. VI, La Haye, Martinus Nijhoff, 1954 ; trad. fr. Gérard Granel, ''La Crise des sciences européennes et la phénoménologie transcendantale'', Paris, Gallimard, 1976.</ref> Le monde de la vie désigne le monde tel qu'il se donne immédiatement dans l'attitude naturelle, avec ses évidences pratiques non thématisées, ses habitudes perceptives stables, ses significations culturelles transmises. Il est inséparable de la facticité de l'existence incarnée et historiquement située.<ref>Depraz, Nathalie, « Alterity and Facticity: New Perspectives on Husserl », ''Husserl Studies'', vol. 14, 1998, p. 1-23.</ref> Husserl reconnaît progressivement que même la conscience transcendantale, qui constitue le monde, ne saurait s'en abstraire complètement. Cette conscience n'est pas une raison pure, désincarnée, flottant au-dessus de toute réalité ; c'est une subjectivité incarnée, prise dans l'histoire, enracinée culturellement. Cette reconnaissance tardive de la dimension factice de la conscience transcendantale a conduit plusieurs interprètes à parler, à propos de Husserl, de « facticité transcendantale ». Ils entendent par là que l'ego transcendantal, tout en demeurant le pôle constituant du monde, possède lui-même une histoire et une effectivité qui ne peuvent pas être entièrement déduites rationnellement.<ref>Breuer, Irene, « Facticity, Necessity and Contingency at Aristotle and Husserl », ''HORIZON. Studies in Phenomenology'', vol. 5, n{{o}} 1, 2016, p. 133-149.</ref> La phénoménologie husserlienne est ainsi travaillée par une tension productive entre l'idéalisme transcendantal qu'elle revendique et la reconnaissance croissante de l'irréductibilité du fait. === Merleau-Ponty et la facticité corporelle === Maurice Merleau-Ponty (1908-1961) opère un déplacement fondamental du concept de facticité en l'attachant intimement à la dimension de l'incarnation corporelle. Dans sa ''Phénoménologie de la perception'' (1945),<ref>Merleau-Ponty, Maurice, ''Phénoménologie de la perception'', Paris, Gallimard, 1945, p. 54.</ref> il montre que la facticité ne constitue pas seulement une condition existentielle abstraite et générale, mais s'incarne concrètement dans le corps propre, ce corps vécu qui n'est ni pure conscience idéelle ni simple objet matériel. Le corps joue pour Merleau-Ponty un rôle ontologiquement central. Il est « une facticité essentielle à la conscience, une synthèse d'intériorité et d'extériorité ».<ref>Merleau-Ponty, Maurice, ''Phénoménologie de la perception'', op. cit., p. 54.</ref> Le corps n'est pas un instrument que la conscience utiliserait depuis l'extérieur, comme un outil que l'on prend ou que l'on abandonne. Il constitue au contraire le médium même par lequel nous sommes au monde, le tissu de notre engagement. Cette facticité corporelle s'exprime dans de multiples dimensions : l'habitude, dont le corps conserve la trace ; la motricité, qui manifeste la capacité du corps à transformer le monde ; la perception, toujours enracinée dans une perspective incarnée. Merleau-Ponty conteste avec vigueur toute conception de la liberté qui prétendrait s'abstraire complètement de la facticité corporelle et historique. Assimiler la facticité à la pure contingence, à un simple obstacle ou à une limitation, serait méconnaître « la plénitude insurpassable du réel ».<ref>Dupond, Pascal, ''Le vocabulaire de Merleau-Ponty'', Paris, Ellipses, 2001, p. 25.</ref> La facticité possède sa propre densité, sa propre logique, qui n'obéit pas aux lois de la nécessité logique, mais à celles de la vie incarnée, aux rythmes du corps, à l'habitude qui sédimente l'expérience. Dans ses derniers travaux, notamment ''Le Visible et l'Invisible'' (resté inachevé, 1964),<ref>Merleau-Ponty, Maurice, ''Le Visible et l'Invisible'', Paris, Gallimard, 1964.</ref> Merleau-Ponty approfondit cette réflexion en développant le concept de « chair » (''chair du monde''). Ce terme désigne l'entrelacement (''Verflechtung'') du sujet et du monde, leur appartenance mutuelle et constitutive, qui dépasse la distinction traditionnelle entre intériorité et extériorité. La facticité n'apparaît dès lors plus comme une simple limitation, mais comme la texture même de notre être-au-monde, son épaisseur irréductible. === Gadamer et l'herméneutique philosophique === Hans-Georg Gadamer (1900-2002), qui a étudié auprès de Heidegger, reprend le concept de facticité dans le cadre de l'herméneutique philosophique systématiquement développée dans ''Vérité et Méthode'' (1960).<ref>Gadamer, Hans-Georg, ''Wahrheit und Methode. Grundzüge einer philosophischen Hermeneutik'', Tübingen, J.C.B. Mohr, 1960 ; trad. fr. Pierre Fruchon, Jean Grondin et Gilbert Merlio, ''Vérité et Méthode'', Paris, Seuil, 1996, p. 324-365.</ref> Pour Gadamer, la facticité désigne ce qui, dans la vie, demeure ultimement infranchissable pour la compréhension, ce qui échappe à toute transparence absolue et résiste à une rationalisation complète. Gadamer souligne que toute tentative de compréhension s'enracine dans une « situation herméneutique » déterminée par la tradition, le langage et l'effectivité historique. Cette « conscience exposée aux effets de l'histoire » (''wirkungsgeschichtliches Bewusstsein'') doit reconnaître avec lucidité sa propre facticité : nous ne pouvons jamais accéder à une position de surplomb absolu par rapport à l'histoire, car nous demeurons toujours déjà engagés, pris dans le mouvement même de la tradition qui nous constitue.<ref>Gadamer, Hans-Georg, ''Vérité et Méthode'', op. cit., p. 324-365.</ref> Loin de constituer un obstacle à la connaissance véritable, cette facticité de la compréhension en fonde la possibilité même. C'est parce que nous sommes historiquement situés que nous pouvons véritablement comprendre : nos « préjugés » (''Vorurteile''), loin d'être des erreurs qu'il faudrait éliminer systématiquement, constituent les conditions positives sans lesquelles toute compréhension demeurerait impossible. Ce que Gadamer nomme la « fusion des horizons » (''Horizontverschmelzung'') entre le texte du passé et le lecteur du présent n'est possible que moyennant cette facticité historique partagée. La facticité n'est donc pas une limitation regrettable dont il faudrait se défaire, mais le fondement même du dialogue vivant entre passé et présent. === Hannah Arendt et la natalité === Hannah Arendt (1906-1975) propose une approche singulière et novatrice de la facticité à travers son concept de « natalité » (''natality''). Dans son ouvrage majeur ''The Human Condition'' (1958),<ref>Arendt, Hannah, ''The Human Condition'', Chicago, University of Chicago Press, 1958 ; trad. fr. Georges Fradier, ''La Condition de l'homme moderne'', Paris, Calmann-Lévy, 1961, p. 97.</ref> Arendt insiste sur le fait que la naissance et la mort ne sont pas de simples événements naturels relevant de l'ordre biologique, mais s'inscrivent dans un monde historico-politique au sein duquel des êtres singuliers apparaissent et disparaissent. La natalité ne se limite nullement au simple fait biologique de venir au monde. Elle désigne plus profondément la capacité humaine fondamentale de commencer, d'initier quelque chose de nouveau, de déployer une action imprévisible qui ne procède pas mécaniquement de causes antécédentes.<ref>Totschnig, Wolfhart, « Arendt's Notion of Natality: An Attempt at Clarification », ''Ideas y Valores'', vol. 66, n{{o}} 165, 2017, p. 327-346.</ref> Précisément parce que nous sommes nés, chacun de nous possède la capacité d'innover, de faire advenir de l'inédit. Chaque naissance introduit dans le monde un être unique qui n'existait pas auparavant, capable de commencer quelque chose d'absolument neuf. Cette conception arendtienne de la natalité transforme profondément notre compréhension de la facticité. Heidegger avait privilégié l'être-vers-la-mort (''Sein zum Tode'') comme horizon ultime de l'existence humaine, comme révélateur suprême de notre condition. Arendt, à l'inverse, insiste sur la natalité en tant que dimension tout aussi constitutive, voire plus fondatrice, de la condition humaine. La facticité de notre naissance n'est pas seulement ce qui nous ''jette'' dans un monde préexistant, ni ce qui nous enferme dans nos déterminations antérieures ; elle nous donne précisément la capacité de transformer ce monde par l'action politique et la parole publique.<ref>Guenther, Lisa, « Being-from-others: Reading Heidegger after Cavarero », ''Hypatia'', vol. 23, n{{o}} 1, 2008, p. 99-118.</ref> === Facticité et pensées non occidentales === Bien que le concept moderne de facticité soit né dans un contexte philosophique européen, des préoccupations voisines traversent de nombreuses traditions philosophiques non occidentales. La pensée bouddhiste, en particulier, accorde une importance majeure à ce qu'on pourrait nommer la facticité à travers les notions de ''dhamma'' (l'ordre des phénomènes) et de ''pratītyasamutpāda'' (origine ou production dépendante).<ref>Guenther, Herbert V., ''Philosophy and Psychology in the Abhidharma'', Berkeley, Shambhala, 1974.</ref> Les êtres existent dans une interdépendance radicale ; rien n'existe isolément ni n'échappe au flux incessant du devenir. Cette vision reconnaît une facticité profonde : nous ne maîtrisons ni nos circonstances de naissance, ni nos conditions d'existence, ni le cours du temps. La philosophie confucéenne, quant à elle, accorde une valeur centrale aux rôles sociaux concrètement donnés et à l'acceptation réfléchie de sa position dans l'ordre social. Le concept de ''li'' (rite, convenance, bienséance) renvoie aux formes rituelles et normatives qui structurent ces relations, relations que l'on ne choisit pas mais que l'on doit intérioriser et accomplir avec excellence.<ref>Jullien, François, ''Traité de l'efficacité'', Paris, Presses Universitaires de France, 1996, p. 45-78.</ref> La vertu consiste non pas à s'en abstraire, mais à les vivre au plus profond, en développant l'harmonie intérieure qui permet de transformer ces contraintes en possibilités d'excellence. La pensée africaine, notamment dans ses expressions philosophiques d'Afrique australe, articule également une réflexion sur la facticité à travers les concepts d'''ubuntu'' et de participation cosmique. L'individu existe toujours au sein d'une communauté concrètement donnée ; il ne peut se définir en dehors des relations facticielles qui le constituent profondément. Selon le dicton zoulou célèbre « umuntu ngumuntu ngabantu » (« l'homme est homme par les autres hommes »),<ref>Louw, Dirk J., « Ubuntu and the Challenges of Multiculturalism in Post-Apartheid South Africa », ''Quest: An African Journal of Philosophy'', vol. 15, n{{os}} 1-2, 2001, p. 15-36.</ref> cette appartenance originaire à une communauté n'est pas choisie, mais elle constitue notre facticité la plus intime et la source même de certaines formes de liberté et de responsabilité. === Enjeux contemporains === La notion de facticité conserve une pertinence cruciale dans les débats philosophiques contemporains, notamment dans les discussions portant sur la liberté humaine, la responsabilité morale et la constitution de l'identité personnelle et collective. Elle permet de penser ensemble la dimension de choix libre et la dimension de non-choix qui caractérisent l'existence humaine dans sa complexité. Dans les débats entre déterminisme biologique et liberté individuelle, le concept de facticité offre une voie théorique intermédiaire. Les êtres humains ne sont ni entièrement déterminés par leurs conditions biologiques, génétiques et socio-économiques, ni absolument libres de s'en abstraire. Notre liberté s'exerce toujours à partir d'une situation donnée que nous n'avons pas créée, mais que nous devons assumer, interpréter et transformer.<ref>Sheehan, Thomas, « Facticity and Ereignis », dans ''Interpreting Heidegger'', Cambridge University Press, 2019, p. 42-68.</ref> Les philosophies contemporaines de l'identité, notamment les travaux critiques sur le genre, la race et la classe sociale, mobilisent la notion de facticité pour éclairer l'articulation complexe entre les assignations sociales imposées et la construction active de soi. Comment comprendre que certains traits (le sexe biologique, la couleur de peau, l'origine sociale) constituent une facticité qui pèse objectivement sur l'existence tout en n'étant jamais un destin totalement irrévocable ? Cette interrogation, déjà centrale chez Beauvoir, demeure philosophiquement brûlante et politiquement urgente. Enfin, le concept de facticité nous oblige à interroger les limites de toute prétention à une rationalisation et à une maîtrise totales de l'existence humaine par la technique ou par la pensée calculante. Contre certains rêves de la modernité occidentale qui visent une transparence complète et une domination intégrale du réel, la facticité rappelle que l'existence humaine conserve toujours une part d'opacité, de contingence, de résistance, qui échappe à la rationalisation instrumentale. Cette dimension facticielle de notre être ne constitue pas un défaut philosophique ou un archaïsme à corriger, mais une caractéristique constitutive de la condition humaine qu'il nous faut reconnaître lucidement et assumer responsablement. === Distinction conceptuelle : facticité et factualité === Il importe de distinguer clairement « facticité » et « factualité », deux termes parfois confondus. La '''factualité''' désigne simplement l'état de ce qui est factuel, c'est-à-dire la réalité brute des faits comme données positives, sans prétention philosophique particulière. Dire qu'il pleut actuellement, c'est affirmer un fait, un énoncé relevant de la factualité, susceptible d'être vrai ou faux. La '''facticité''', au contraire, renvoie à l'ordre de la contingence et de la situation existentielle, au mode d'être singulier de l'existence incarnée. Elle ne porte pas sur les faits en tant que contenus de propositions, mais sur la structure de l'existence elle-même : le fait qu'existe un sujet qui n'a pas choisi d'exister, qui ne peut en aucune façon faire abstraction de son être-là, et qui doit pourtant assumer cette condition pour la transformer en destin singulier. == Notes et références == {{references}} === Bibliographie === ==== Sources primaires ==== * Arendt, Hannah, ''The Human Condition'', Chicago, University of Chicago Press, 1958. * Beauvoir, Simone de, ''Pour une morale de l'ambiguïté'', Paris, Gallimard, 1947. * Beauvoir, Simone de, ''Le Deuxième Sexe'', Paris, Gallimard, 1949. * Fichte, Johann Gottlieb, ''Wissenschaftslehre'' (1804), éd. et trad. Isabelle Thomas-Fogiel, Paris, Presses Universitaires de France, 2011. * Gadamer, Hans-Georg, ''Wahrheit und Methode'', Tübingen, J.C.B. Mohr, 1960 ; trad. fr. ''Vérité et Méthode'', Paris, Seuil, 1996. * Heidegger, Martin, ''Phänomenologie des religiösen Lebens'' (1920-1921), Gesamtausgabe, vol. 60, Francfort-sur-le-Main, Vittorio Klostermann, 1995 ; trad. fr. ''Phénoménologie de la vie religieuse'', Paris, Gallimard, 2011. * Heidegger, Martin, ''Ontologie. Hermeneutik der Faktizität'' (1923), Gesamtausgabe, vol. 63, Francfort-sur-le-Main, Vittorio Klostermann, 1988 ; trad. fr. ''Ontologie. Herméneutique de la facticité'', Paris, Gallimard, 1992. * Heidegger, Martin, ''Sein und Zeit'' (1927), Tübingen, Max Niemeyer Verlag, 1967 ; trad. fr. ''Être et Temps'', Paris, Gallimard, 1986. * Husserl, Edmund, ''Die Krisis der europäischen Wissenschaften und die transzendentale Phänomenologie'' (1936), Husserliana, vol. VI, La Haye, Martinus Nijhoff, 1954 ; trad. fr. ''La Crise des sciences européennes et la phénoménologie transcendantale'', Paris, Gallimard, 1976. * Kant, Immanuel, ''Kritik der praktischen Vernunft'' (1788) ; trad. fr. ''Critique de la raison pratique'', Paris, Presses Universitaires de France, 1943. * Merleau-Ponty, Maurice, ''Phénoménologie de la perception'', Paris, Gallimard, 1945. * Merleau-Ponty, Maurice, ''Le Visible et l'Invisible'', Paris, Gallimard, 1964. * Sartre, Jean-Paul, ''L'Être et le Néant. Essai d'ontologie phénoménologique'', Paris, Gallimard, 1943. * Sartre, Jean-Paul, ''L'Existentialisme est un humanisme'', Paris, Nagel, 1946. ==== Études critiques ==== * Breuer, Irene, « Facticity, Necessity and Contingency at Aristotle and Husserl », ''HORIZON. Studies in Phenomenology'', vol. 5, n{{o}} 1, 2016, p. 133-149. * Bruno, G. Anthony, « Facticity and Genesis: Tracking Fichte's Method in the Berlin Wissenschaftslehre », ''Fichte-Studien'', vol. 49, 2021, p. 177-197. * Bruno, G. Anthony, ''Facticity and the Fate of Reason After Kant'', Oxford, Oxford University Press, 2025. * Coorebyter, Vincent de, « De la contingence à la situation : dimensions et configurations de la facticité dans ''L'Être et le Néant'' », ''Études sartriennes'', n{{o}} 4, 2000, p. 133-174. * Depraz, Nathalie, « Alterity and Facticity: New Perspectives on Husserl », ''Husserl Studies'', vol. 14, 1998, p. 1-23. * Dupond, Pascal, ''Le vocabulaire de Merleau-Ponty'', Paris, Ellipses, 2001. * Garcia, Manon, « Les ''Mémoires'' comme œuvre philosophique », ''Simone de Beauvoir Studies'', vol. 29, 2018, p. 71-86. * Guenther, Herbert V., ''Philosophy and Psychology in the Abhidharma'', Berkeley, Shambhala, 1974. * Guenther, Lisa, « Being-from-others: Reading Heidegger after Cavarero », ''Hypatia'', vol. 23, n{{o}} 1, 2008, p. 99-118. * Jullien, François, ''Traité de l'efficacité'', Paris, Presses Universitaires de France, 1996. * Loidolt, Sophie, « Husserl and the Fact of Practical Reason », ''Recherches husserliennes'', vol. 35, 2011, p. 17-42. * Longtin, Ryan A., « Reconsidering Heidegger's Appropriation of Dilthey », ''Continental Philosophy Review'', vol. 54, 2021, p. 371-391. * Louw, Dirk J., « Ubuntu and the Challenges of Multiculturalism in Post-Apartheid South Africa », ''Quest: An African Journal of Philosophy'', vol. 15, n{{os}} 1-2, 2001, p. 15-36. * Nelson, Eric Sean, « Empiricism, Facticity, and the Immanence of Life in Dilthey », ''Journal of the British Society for Phenomenology'', vol. 38, n{{o}} 3, 2007, p. 299-313. * Sheehan, Thomas, « Facticity and Ereignis », dans ''Interpreting Heidegger'', Cambridge University Press, 2019, p. 42-68. * Totschnig, Wolfhart, « Arendt's Notion of Natality: An Attempt at Clarification », ''Ideas y Valores'', vol. 66, n{{o}} 165, 2017, p. 327-346. * Warkocki, Witold, ''La notion heideggérienne de facticité dans le contexte de la destruction de l'histoire de l'ontologie'', thèse de doctorat, Université Toulouse-Jean Jaurès, 2019. === Voir aussi === * Contingence * {{Page|Dasein}} * Existentialisme * Liberté * Phénoménologie * Situation * Transcendance {{autocat}} ptrlfgfo26vhgej5fwwnkbl6sjk5fp3 Dictionnaire de philosophie/Erreur 0 83207 768458 767904 2026-06-24T03:16:33Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768458 wikitext text/x-wiki {{DicoPhilo|Erreur|lecture=oui}} L'erreur désigne, au sens philosophique le plus général, un jugement faux, une croyance inadéquate ou une représentation inexacte de la réalité. Elle se distingue du mensonge (qui implique l'intention de tromper), de l'ignorance (qui est l'absence de connaissance) et de l'illusion (qui est une perception déformée). La question de l'erreur est centrale en épistémologie, car elle soulève le problème fondamental des conditions et des limites de la connaissance humaine : comment pouvons-nous nous tromper, et comment pouvons-nous corriger ou éviter l'erreur ? == Définitions et distinctions == === Nature et types d'erreurs === L'erreur peut être définie simplement comme l'inadéquation entre notre jugement et la réalité. Cependant, cette définition générale englobe plusieurs types distincts d'erreurs : * L'erreur factuelle : porter un jugement faux sur un état de choses (« Le soleil tourne autour de la Terre ») * L'erreur logique : commettre une faute dans un raisonnement, même si les prémisses sont vraies * L'erreur méthodologique : employer une mauvaise méthode pour parvenir à la connaissance * L'erreur morale : se tromper sur ce qui est bien ou mal, juste ou injuste Cette classification montre que l'erreur n'est pas un phénomène unifié. Elle intervient à différents niveaux de notre vie cognitive et pratique. === Erreur et vérité === L'erreur n'a de sens philosophique que par rapport à la vérité. Dès l'Antiquité, les penseurs ont reconnu la profondeur du problème. Xenophane (VI{{e}} siècle av. J.-C.) formule déjà l'aporie fondamentale : « Nul homme n'a connu ni ne connaîtra jamais la vérité certaine sur les dieux et sur toutes les choses dont je parle. Car même si, par le plus grand des hasards, il venait à dire la vérité, il ne le saurait pas lui-même, car tout n'est qu'opinion. »<ref>Xenophane, fragment DK 21 B 34</ref> Cette parole ancienne pose le problème épistémologique essentiel : même si nous énonçons la vérité, comment savoir que nous ne nous trompons pas ? == L'Antiquité grecque et romaine == === Platon et le problème de la possibilité de l'erreur === Dans le ''Théétète'', Platon pose la question apparemment paradoxale : comment l'erreur est-elle possible ? Si nous connaissons quelque chose, nous ne pouvons nous tromper à son sujet. Si nous ne la connaissons pas, nous ne pouvons rien en dire. Comment peut-on alors se tromper ?<ref>Platon, ''Théétète'', 188a-c</ref> Platon propose plusieurs solutions pour résoudre ce paradoxe. Dans la théorie de la « tablette de cire » (''plax kai keros''), l'âme ressemble à une plaque de cire sur laquelle les perceptions s'impriment. L'erreur survient quand nous appliquons la mauvaise empreinte à la mauvaise perception. L'image est celle du sceau : si le sceau ne correspond pas à l'impression, l'erreur se produit. Dans la ''République'', Platon établit également une hiérarchie des états mentaux, du bas en haut : l'opinion (''doxa''), la croyance (''pistis''), l'intellection (''dianoia'') et enfin la connaissance scientifique (''epistémè''). L'erreur réside largement dans la confusion entre ces niveaux.<ref>Platon, ''République'', Livre VI, 509d-511e</ref> === Aristote et l'erreur dans le jugement === Aristote concentre son analyse de l'erreur sur le jugement, considéré comme le lieu propre où l'erreur se produit. Dans le ''De l'interprétation'', il établit la distinction fondamentale : une proposition est vraie si elle dit de ce qui est qu'il est, ou de ce qui n'est pas qu'il n'est pas. Elle est fausse dans le cas contraire.<ref>Aristote, ''Métaphysique'', Livre Γ (Gamma), 1011b25-27</ref> C'est une formulation précoce de la théorie de la vérité-correspondance. Aristote identifie aussi les paralogismes (raisonnements incorrects formellement) et les sophismes (raisonnements trompeurs intentionnels). Dans les ''Réfutations sophistiques'', il analyse systématiquement les moyens par lesquels on peut induire l'erreur par la parole. Un point crucial chez Aristote est que l'erreur peut provenir de prémisses fausses dans un raisonnement logiquement correct. Même un syllogisme parfait ne produit la science véritable (''epistémè'') que s'il repose sur des prémisses vraies et premières. C'est pourquoi, dans les ''Seconds Analytiques'', Aristote souligne que la science authentique exige non seulement un raisonnement valide, mais aussi des principes véritables et premiers.<ref>Aristote, ''Seconds Analytiques'', I, 2, 71b9-72a5</ref> === La doctrine stoïcienne de l'assentiment === Pour les stoïciens, l'erreur n'est pas simplement une affaire de contenu faux, mais d'un mauvais usage de la faculté d'assentiment (''sunkatathesis'' en grec, ''assensio'' en latin). Cette analyse introduit une dimension volontaire dans l'erreur qui était moins présente chez les platoniciens. La représentation (''phantasia'') vient à l'esprit de façon passive. Mais l'assentiment à cette représentation est un acte volontaire de notre raison. L'erreur survient précisément quand nous donnons notre assentiment à une représentation qui n'est pas « compréhensive » (''kataleptikè phantasia''), c'est-à-dire qui ne garantit pas sa propre vérité par son caractère d'évidence intrinsèque.<ref>Cicéron, ''Académiques'' II, xii, 37</ref> Le sage stoïcien, selon cette doctrine, s'abstient précisément de donner son assentiment aux représentations non compréhensives. Cette suspension volontaire du jugement (proche de l'epochè des sceptiques) est le moyen d'éviter l'erreur. Les stoïciens insistent : nous ne sommes jamais forcés d'assentir. C'est par un choix que nous nous trompons, ce qui rend l'erreur une forme de faute morale.<ref>Épictète, ''Entretiens'', II, xx, 28-31</ref> Cette conception a profondément influencé les débats entre les stoïciens et les sceptiques académiciens (comme Arcésilas et Carnéade), qui arguaient qu'aucune représentation n'est jamais suffisamment compréhensive pour garantir l'absence d'erreur. Pour les sceptiques, il faut donc suspendre l'assentiment sur toutes choses. == La philosophie médiévale == === Augustin : l'erreur, le libre arbitre et le péché === Saint Augustin reprend et transforme profondément la problématique platonicienne de l'erreur. Dans le ''De libero arbitrio'' (''Du libre arbitre''), il établit que l'erreur provient non d'un défaut de nos facultés cognitives (qui viennent de Dieu et sont donc bonnes en elles-mêmes), mais d'un détournement volontaire de notre libre arbitre.<ref>Augustin, ''De libero arbitrio'', II, 19</ref> Augustin opère un basculement décisif : le problème n'est pas gnoséologique mais moral. Nous nous trompons parce que notre volonté se détourne du Bien suprême (Dieu) pour se porter vers les biens inférieurs. L'erreur devient ainsi une forme de désordre de la volonté. Pour Augustin, l'erreur a aussi une dimension historique et existentielle. Elle est liée au péché originel qui a obscurci notre intelligence et affaibli notre volonté. La connaissance véritable nécessite donc une illumination divine (''illuminatio divina''), une participation à la lumière éternelle de Dieu. Sans cette grâce, nous restons en proie à l'erreur et aux illusions des sens et de l'imagination. === Thomas d'Aquin : intellect, jugement et composition === Thomas d'Aquin, reprenant la distinction aristotélicienne, soutient que l'erreur ne peut pas provenir de l'intellect en tant que tel, car l'intellect saisit correctement son objet propre (les essences intelligibles). L'erreur se produit plutôt dans le jugement, quand l'intellect compose ou divise des concepts.<ref>Thomas d'Aquin, ''Somme théologique'', Ia, question 17, article 3</ref> Thomas introduit aussi une distinction cruciale : l'erreur est une fausse connaissance, un jugement tenu pour vrai alors qu'il est faux. Elle se distingue de l'ignorance (simple absence de connaissance) et de la non-connaissance (absence de la faculté elle-même). Cette triple distinction affine considérablement notre compréhension du phénomène. Thomas analyse également en détail les causes de l'erreur : les prémisses fausses, le raisonnement incorrect, l'influence des passions sur le jugement, les préjugés de l'éducation. Il reconnaît que notre volonté peut nous pousser à juger avant d'avoir des preuves suffisantes, et que nos désirs et aversions influencent nos jugements. == La philosophie moderne == === Descartes : précipitation de la volonté et usage impropre du libre arbitre === Dans les ''Méditations métaphysiques'', Descartes place le problème de l'erreur au cœur de sa réflexion philosophique. Sa question est celle-ci : comment Dieu, qui est parfait et véridique, a-t-il pu créer des êtres sujets à l'erreur ? La solution cartésienne est révolutionnaire. Elle réside dans la ''Méditation quatrième'' : l'erreur provient de la disproportion entre notre entendement (faculté passive de concevoir), qui est fini, et notre volonté (faculté active de juger), qui est infinie. L'entendement nous présente des idées claires ou confuses, mais c'est la volonté qui affirme ou nie. L'erreur survient quand nous jugeons (acte de la volonté) avant ou sans que l'entendement ait une perception suffisamment claire et distincte.<ref>Descartes, ''Méditations métaphysiques'', Méditation quatrième, Adam-Tannery IX, 46</ref> Le problème, selon Descartes, n'est pas que nous puissions nous tromper (ce qui serait blâmable à Dieu), mais que nous ''choisissons'' de nous tromper par une sorte de précipitation ou de précipité (''praecipitatio''). Descartes écrit : « Si je m'abstiens de donner mon jugement sur une chose, lorsque je ne la conçois pas avec assez de clarté et de distinction, il est évident que j'en use fort bien, et que je ne suis point trompé. »<ref>Descartes, ''Méditations métaphysiques'', Méditation quatrième, Adam-Tannery IX, 47</ref> Ainsi, Dieu n'est pas responsable de nos erreurs ; nous sommes responsables du mauvais usage de notre libre arbitre. La règle pour éviter l'erreur est donc celle de l'évidence : ne juger que de ce qui nous apparaît clairement et distinctement. === Spinoza : l'erreur comme privation et inadéquation === Spinoza, dans l'''Éthique'', rejette la solution cartésienne. Pour lui, l'erreur n'est pas due à un mauvais usage de la volonté (qu'il refuse de distinguer réellement de l'entendement). Au contraire, l'erreur est simplement une privation de connaissance, c'est-à-dire une forme d'ignorance.<ref>Spinoza, ''Éthique'', Deuxième Partie, proposition 35</ref> Une idée fausse n'est pas quelque chose de positif, une sorte de tromperie active. C'est plutôt une idée inadéquate, c'est-à-dire une idée incomplète ou partielle. Spinoza donne l'exemple célèbre du soleil : quand nous le voyons, il semble se trouver à deux cents pieds de nous. Cette apparence persiste même quand nous savons scientifiquement que le soleil est beaucoup plus éloigné. L'apparence elle-même ne constitue pas une erreur : elle est une idée vraie de l'affection de notre corps par la lumière solaire. L'erreur consiste plutôt dans l'ignorance de la vraie distance du soleil, ignorance qui nous pousse à croire en la proximité apparente.<ref>Spinoza, ''Éthique'', Deuxième Partie, proposition 35, scolie</ref> Pour Spinoza, la connaissance progresse en trois genres : du premier genre (expérience directe et imagination), au deuxième genre (connaissance rationnelle des propriétés communes), au troisième genre (intuition des essences particulières sous l'espèce de l'éternité). L'erreur réside dans la prédominance du premier genre de connaissance. === Locke : les sources de l'erreur dans le jugement === John Locke, fondateur de l'empirisme moderne, situe l'origine de l'erreur dans l'acte de jugement. Dans l'''Essai sur l'entendement humain'', il opère une distinction cruciale : la connaissance est la perception de l'accord ou du désaccord entre nos idées. Le jugement, en revanche, est notre façon de suppléer au manque de certitude dans la connaissance.<ref>Locke, ''Essai sur l'entendement humain'', Livre IV, chapitre XIV</ref> Locke identifie quatre sources principales de l'erreur : * Le manque de preuves : nous jugeons sans avoir suffisamment d'évidence * La mauvaise utilisation des preuves disponibles : nous manquons d'habileté à nous servir correctement de ce que nous savons * Le manque de volonté de chercher : nous ne nous donnons pas la peine d'acquérir les preuves nécessaires * Les fausses mesures de probabilité : nous laissons nos désirs, nos préjugés et nos passions fausser notre évaluation des probabilités Locke insiste particulièrement sur l'erreur qui provient des mots et du langage. Souvent, nous croyons avoir des idées clares alors que nous possédons simplement des mots vagues ou mal définis. Cette confusion entre les mots et les idées qu'ils sont censés exprimer est une source majeure d'erreur, notamment en philosophie et en théologie.<ref>Locke, ''Essai sur l'entendement humain'', Livre III, chapitre XI</ref> === Leibniz : les petites perceptions et la confusion === Leibniz enrichit la compréhension de l'erreur en introduisant sa théorie des petites perceptions (''infinitesimal perceptions''). Selon lui, nous avons une infinité de perceptions inconscientes ou subliminales : trop petites, trop nombreuses, trop habituelles pour être remarquées individuellement. Ces perceptions confuses influencent nos jugements sans que nous en soyons conscients.<ref>Leibniz, ''Nouveaux essais sur l'entendement humain'', Préface</ref> L'erreur peut ainsi provenir de perceptions confuses qui échappent à notre aperception consciente. Leibniz donne l'exemple célèbre du bruit de la mer : nous entendons le bruit de chaque vague individuellement, et même de chaque goutte d'eau, mais nous ne percevons pas distinctement chacune de ces perceptions. Nous ne percevons que leur ensemble confus. De même, beaucoup de nos erreurs proviennent de perceptions distinctes que nous ne discernons pas clairement. Leibniz maintient cependant un principe fondamental : toute erreur est ultimement une forme de confusion (''confusio''). Une connaissance parfaitement claire et distincte ne peut être erronée. L'erreur est donc toujours un défaut de clarté dans nos représentations mentales. === Kant : l'erreur, l'illusion et l'illusion transcendantale === Dans la ''Critique de la raison pure'', Kant opère une révolution dans la conception de l'erreur. Il distingue nettement l'erreur de l'illusion (''Schein''). L'erreur est un jugement qui peut être reconnu comme faux et corrigé. L'illusion, en revanche, est plus profonde : c'est une apparence qui persiste même après qu'on ait reconnu qu'elle est trompeuse (comme les illusions d'optique classiques).<ref>Kant, ''Critique de la raison pure'', Première Critique, A293-294/B349-350</ref> Kant donne un exemple instructif : si un bâton plongé dans l'eau semble courbé, l'erreur consiste à croire que le bâton est réellement courbé. Mais si, même après avoir compris que le bâton n'est pas courbé, on continue à le percevoir comme courbé, c'est une illusion. Kant identifie l'illusion transcendantale, qui est l'illusion propre à la raison pure elle-même. Cette illusion nous pousse naturellement à appliquer les catégories de l'entendement au-delà de leur domaine d'application légitime (l'expérience possible) et à prétendre connaître les choses en soi. C'est ainsi que naissent les erreurs fondamentales de la métaphysique traditionnelle : la prétention à connaître Dieu, l'âme immortelle et le monde considéré comme une totalité absolue, alors que ces objets dépassent les limites de toute expérience possible.<ref>Kant, ''Critique de la raison pure'', Première Critique, A293-298/B349-355</ref> La ''Dialectique transcendantale'' de Kant, qui occupe la moitié de la ''Critique'', analyse systématiquement ces illusions de la raison pure. Kant montre que ces erreurs ne sont pas accidentelles ou évitables, mais qu'elles naissent nécessairement de la structure même de notre raison. La raison tend naturellement à chercher l'inconditionné au-delà de toute expérience possible. C'est ainsi que se constituent les trois idées de la raison pure : l'âme (inconditionnée des phénomènes mentaux), le monde (totalité inconditionnée de tous les phénomènes), et Dieu (cause inconditionnée de toute existence). == La philosophie des sciences == === Francis Bacon : la théorie des idoles de l'esprit === Francis Bacon, au début de l'époque moderne, fait de la question des sources d'erreur un élément central de sa philosophie de la nature. Dans le ''Novum Organum'' (1620), il introduit sa célèbre théorie des idoles (''idola'') de l'esprit, c'est-à-dire de sources systématiques d'erreur qui offusquent l'esprit humain et l'empêchent d'accéder à la connaissance véritable de la nature.<ref>Bacon, ''Novum Organum'', Livre I, aphorismes 39-68</ref> Bacon identifie quatre types d'idoles : * Les idoles de la tribu (''idola tribus'') : erreurs communes à tous les êtres humains, qui proviennent de la nature humaine elle-même. Par exemple, la tendance à voir plus d'ordre et d'uniformité qu'il n'y en a réellement, ou à généraliser à partir d'exemples trop rares. * Les idoles de la caverne (''idola specus'') : erreurs particulières à chaque individu, qui proviennent de son éducation, de ses lectures, de ses préférences et de son tempérament personnel. Chacun a sa propre « caverne » de préjugés. * Les idoles du forum ou du marché (''idola fori'') : erreurs provenant de l'usage du langage et des mots mal définis. Les mots trompent l'entendement, car ils ne correspondent pas toujours aux réalités qu'ils prétendent désigner. * Les idoles du théâtre (''idola theatri'') : erreurs dues aux systèmes philosophiques reçus et aux dogmes des écoles. Bacon les compare à des pièces de théâtre ou à des fables qui nous présentent des mondes imaginaires. Bacon insiste sur la nécessité d'une libération systématique de ces idoles pour permettre à la connaissance scientifique de progresser. Il promeut une méthode rigoureuse fondée sur l'expérimentation contrôlée et l'induction prudente, à la place du raisonnement déductif des aristotéliciens. === Gaston Bachelard : l'obstacle épistémologique === Gaston Bachelard, dans ''La Formation de l'esprit scientifique'' (1938), introduit le concept révolutionnaire d'obstacle épistémologique. Contrairement aux obstacles matériels, l'obstacle épistémologique est interne à l'acte même de connaître. C'est une connaissance antérieure, ou plutôt une pseudo-connaissance, qui fait obstacle à une connaissance nouvelle et plus adéquate.<ref>Bachelard, ''La Formation de l'esprit scientifique'', Paris, Vrin, 1938, p. 13</ref> Bachelard énonce une proposition paradoxale et profonde : « On connaît contre une connaissance antérieure. »<ref>Bachelard, ''La Formation de l'esprit scientifique'', p. 14</ref> L'obstacle n'est donc pas simplement l'ignorance, mais précisément une connaissance première ou immédiate qui empêche l'accès à la connaissance scientifique. L'expérience première, loin d'être le fondement de la science, en est souvent le plus grand obstacle. Bachelard identifie plusieurs types d'obstacles épistémologiques : * L'expérience première : l'observation directe non questionnée, la tendance à croire ce qu'on voit * La généralisation hâtive : tirer des conclusions générales à partir d'expériences limitées * L'obstacle verbal : croire qu'expliquer un phénomène revient à le nommer * L'obstacle substantialiste : attribuer à une substance des qualités diverses et souvent contradictoires * L'obstacle animiste : projeter la vie et l'intention dans la matière inerte * La connaissance quantitative mal comprise : croire que mesurer c'est comprendre Pour Bachelard, la science progresse non par accumulation graduelle, mais par ruptures épistémologiques qui exigent de surmonter ces obstacles. L'esprit scientifique doit constamment lutter contre lui-même, contre ses propres habitudes de pensée et ses préjugés les plus tenaces. === Karl Popper : falsifiabilité et correction de l'erreur === Karl Popper transforme radicalement la conception de l'erreur en philosophie des sciences. Dans ''La Logique de la découverte scientifique'' (1934), il soutient que la science ne progresse pas par accumulation ou confirmation de vérités, mais par élimination des erreurs.<ref>Popper, ''La Logique de la découverte scientifique'', Payot, 1973, p. 54-57</ref> Popper rejette le principe de vérification des positivistes logiques et lui substitue le principe de falsifiabilité ou de réfutabilité : une théorie n'est scientifique que si elle peut être contredite par une observation empirique possible. Une théorie qui ne peut jamais être réfutée, parce qu'elle est compatible avec tous les résultats empiriques possibles, n'est pas scientifique.<ref>Popper, ''Conjectures et réfutations'', Payot, 1985, p. 64-65</ref> Pour Popper, toute connaissance scientifique est essentiellement conjecturale : nous ne pouvons jamais prouver qu'une théorie est véritablement vraie, nous pouvons seulement prouver qu'elle est fausse. Une théorie qui a résisté à des tentatives répétées de réfutation est dite corroborée, mais jamais définitivement vérifiée. L'erreur n'est donc pas quelque chose à redouter ou à éliminer complètement, mais elle est essentielle au processus scientifique lui-même. Comme Popper l'écrit : « Nous pouvons apprendre de nos erreurs. »<ref>Popper, ''Objective Knowledge'', Clarendon Press, 1972, p. 7</ref> C'est en identifiant nos théories comme fausses, en les réfutant expérimentalement, que nous avançons graduellement vers une meilleure compréhension du monde. Toute erreur qui peut être reconnue et éliminée par la méthode scientifique est une victoire pour la science. == La psychologie cognitive contemporaine == === Heuristiques et biais cognitifs === À partir des années 1970, les psychologues et lauréats du prix Nobel Daniel Kahneman et Amos Tversky ont développé une théorie révolutionnaire des heuristiques et des biais cognitifs qui a renouvelé profondément notre compréhension des erreurs humaines. Une heuristique est un raccourci mental, une règle de raisonnement simple et pragmatique que nous utilisons automatiquement et, le plus souvent, inconsciemment pour résoudre des problèmes complexes. Les heuristiques sont généralement utiles et efficaces, permettant un traitement cognitif économe. Cependant, elles peuvent aussi conduire à des erreurs systématiques et prévisibles, appelées biais cognitifs.<ref>Kahneman, D., Slovic, P., et Tversky, A. (éd.), ''Judgment under Uncertainty: Heuristics and Biases'', Cambridge University Press, 1982</ref> Kahneman et Tversky ont identifié trois heuristiques principales : * L'heuristique de représentativité : nous jugeons de la probabilité qu'un objet appartienne à une catégorie en fonction de sa ressemblance avec le prototype typique de cette catégorie, en ignorant souvent d'autres informations statistiques pertinentes. * L'heuristique de disponibilité : nous jugeons de la fréquence ou de la probabilité d'un événement en fonction de la facilité avec laquelle des exemples nous viennent spontanément à l'esprit, ce qui peut nous faire surestimer les événements dramatiques ou médiatisés. * L'heuristique d'ancrage et d'ajustement : notre jugement est influencé de façon disproportionnée par une valeur initiale (l'ancre), même si cette valeur est arbitraire ou irrélevante, et nous ajustons insuffisamment à partir de cette valeur. === Les principaux biais cognitifs === Ces heuristiques produisent de nombreux biais cognitifs, dont voici quelques exemples majeurs : * Le biais de confirmation : tendance sélective à chercher, à favoriser et à mémoriser les informations qui confirment nos croyances préexistantes, tout en ignorant ou minimisant les informations qui les contredisent. * Le biais rétrospectif (ou ''hindsight bias'') : tendance à surestimer, après coup, la probabilité ou la prévisibilité d'un événement qui s'est produit. On dit souvent « Je le savais depuis le début ». * L'excès de confiance : tendance à surestimer la précision de nos connaissances et la justesse de nos jugements, notamment dans les domaines où nous avons une expertise. * Le biais d'ancrage : influence disproportionnée d'une première information reçue sur nos jugements ultérieurs, même quand cette information est clairement non pertinente ou reconnue comme inexacte. * L'erreur du joueur : croyance erronée que des événements indépendants (comme les lancers d'une pièce de monnaie) sont liés ou influencés par les résultats antérieurs. Cette recherche montre que l'erreur humaine n'est pas simplement due à un manque d'attention, à la fatigue ou à l'ignorance, mais qu'elle est systématique et prévisible. Nous commettons des erreurs non ''malgré'' nos processus de pensée, mais ''à cause'' d'eux. Même les experts reconnaissent qu'ils sont sujets à ces biais. === Système 1 et Système 2 de la pensée === Kahneman a synthétisé ces résultats en distinguant deux systèmes de pensée dans son livre ''Thinking, Fast and Slow'' (2011). Le Système 1 est rapide, automatique, intuitif et demande peu d'effort, mais il est sujet aux biais cognitifs. Le Système 2 est lent, délibératif, logique et demande un effort cognitif considérable, mais il est généralement plus fiable.<ref>Kahneman, D., ''Système 1, Système 2 : Les deux vitesses de la pensée'', Flammarion, 2012</ref> La plupart de nos erreurs proviennent du fait que nous nous fions trop au Système 1, au lieu d'engager notre Système 2 plus réflexif. Le Système 1 nous permet de vivre efficacement dans un monde complexe et de prendre rapidement des décisions, mais il nous rend aussi vulnérables aux erreurs systématiques et aux illusions cognitives. Reconnaître cette distinction est une étape importante pour améliorer notre capacité à éviter les erreurs, notamment en contexte scientifique ou décisionnel. == Les traditions non-occidentales == === Le bouddhisme : l'ignorance comme racine de la souffrance === Dans le bouddhisme, l'avidyā (l'ignorance) est considérée comme la racine primaire de la souffrance (''dukkha''). Mais il ne s'agit pas simplement d'un manque de connaissance factuelle ou intellectuelle. C'est une méconnaissance fondamentale de la nature profonde de la réalité. Les Quatre Nobles Vérités enseignées par le Bouddha identifient l'ignorance comme la cause première de la souffrance. Cette ignorance porte essentiellement sur trois caractéristiques fondamentales de l'existence, appelées les Trois Caractéristiques: * L'impermanence (''anicca'') : tout phénomène est en changement constant. Rien n'est permanent ou éternel. * La souffrance ou l'insatisfaction (''dukkha'') : tout phénomène conditionné est marqué par l'insatisfaction ou l'insuffisance. * Le non-soi (''anattā'') : il n'existe pas de moi permanent, autonome et substantiel. Le soi est une construction fictive. L'erreur fondamentale consiste à croire en la permanence des choses, en l'existence d'un soi essentiellement permanent, et à s'attacher aux phénomènes impermanents. Cette erreur n'est pas simplement théorique : elle structure profondément notre façon de vivre et engendre inévitablement la souffrance. Le bouddhisme identifie également les Trois Poisons qui perpétuent cette ignorance fondamentale : * Le désir-attachement (''rāga''): la tendance à nous accrocher aux plaisirs et à ce qui nous plaît * L'aversion-haine (''dveṣa''): le rejet de ce qui nous déplaît ou nous fait souffrir * L'ignorance-illusion (''moha''): la méconnaissance de la nature réelle des choses La voie bouddhiste vers la libération (''nirvāṇa'') consiste précisément à dissiper cette ignorance fondamentale par la pratique de la sagesse (''prajñā''), de l'éthique (''śīla'') et de la méditation (''samādhi''). La connaissance libératrice n'est pas simplement intellectuelle ou théorique, mais elle doit être experiencielle : voir directement, par une expérience méditative, la nature réellement impermanente, insatisfaisante et sans-soi de tous les phénomènes. Dans le bouddhisme Mahāyāna, notamment dans la philosophie Madhyamaka de Nāgārjuna (II{{e}}-III{{e}} siècle), l'erreur métaphysique fondamentale est identifiée à la croyance en l'existence inhérente (''svabhāva'') des phénomènes. Nāgārjuna enseigne la vacuité (''śūnyatā'') : tous les phénomènes sont vides d'existence propre ou substantielle. Ils existent seulement en interdépendance avec d'autres phénomènes, selon le principe de production conditionnée (''pratītyasamutpāda''). L'erreur métaphysique par excellence est donc la réification, c'est-à-dire attribuer aux phénomènes une substantialité ou une existence autonome qu'ils n'ont pas. == Conclusion == La notion d'erreur traverse toute l'histoire de la philosophie et demeure une question centrale en épistémologie contemporaine. De Platon à Kahneman, en passant par Descartes, Bachelard et Popper, les penseurs ont cherché à comprendre les mécanismes profonds de l'erreur, ses origines et ses remèdes. Plusieurs leçons majeures émerges de cette histoire réflexive : 1. L'erreur est inévitable. Dès l'Antiquité, avec Xenophane, et plus explicitement avec le fallibilisme moderne (Popper), la philosophie reconnaît que la connaissance humaine est essentiellement faillible. Même nos meilleures théories scientifiques ne sont que provisoires et susceptibles d'être réfutées par de nouvelles preuves. Il n'existe pas de point d'Archimède d'où nous puissions connaître avec certitude absolue. 2. L'erreur a des causes multiples et systématiques. Elle n'est pas simplement due à des défauts accidentels ou à un manque d'attention. Elle provient de la structure même de nos facultés cognitives, de nos habitudes mentales, de nos préjugés culturels, et de nos processus psychologiques automatiques. Les biais cognitifs montrent que nous commettons des erreurs non ''malgré'' nos mécanismes mentaux, mais ''par suite'' de leur fonctionnement. 3. L'erreur peut être féconde et créatrice. Contrairement à une conception purement négative de l'erreur, Bachelard et Popper montrent que l'erreur est essentielle au progrès de la connaissance. C'est en identifiant et en corrigeant nos erreurs que nous progressons vers une compréhension plus adéquate. La science progresse par conjecture et réfutation, par essai et correction d'erreurs. 4. La vigilance épistémique est nécessaire. Que ce soit la suspension du jugement stoïcienne, la règle de l'évidence cartésienne, la méthode expérimentale de Bacon, ou la conscience contemporaine des biais cognitifs, toutes ces approches soulignent la nécessité d'une vigilance critique constante pour minimiser l'erreur. Nous ne pouvons pas nous fier passivement à nos impressions ou à nos intuitions. 5. L'erreur a une dimension existentielle et pratique. Particulièrement dans les traditions non-occidentales comme le bouddhisme, l'erreur n'est pas seulement un problème théorique de connaissance, mais elle a des conséquences profondes pour notre existence et notre bien-être. Notre façon de comprendre le monde (ou de nous y tromper) détermine notre manière de vivre et notre rapport à la souffrance. À l'époque contemporaine, la question de l'erreur se repose avec une acuité nouvelle. L'époque des « fake news » et de la désinformation massive, l'amplification des biais cognitifs par les algorithmes des réseaux sociaux, et la fragmentation de nos espaces informationnels rendent plus urgent que jamais de comprendre les mécanismes de l'erreur et de développer nos capacités critiques. La philosophie de l'erreur, loin d'être une discipline abstraite, est devenue une ressource indispensable pour naviguer dans notre monde complexe et pluraliste. == Notes et références == {{references|colonnes=2}} == Bibliographie == === Sources primaires === * Aristote, ''Métaphysique'', traduction J. Tricot, Vrin, 1991 * Aristote, ''Seconds Analytiques'', traduction J. Tricot, Vrin, 1987 * Augustin, ''Du libre arbitre'', traduction F.-J. Thonnard, Desclée de Brouwer, 1952 * Bacon, F., ''Novum Organum'', traduction M. Malherbe et J.-M. Pousseur, PUF, 1986 * Bachelard, G., ''La Formation de l'esprit scientifique'', Vrin, 1938 * Descartes, R., ''Méditations métaphysiques'', édition J.-M. Beyssade et M. Beyssade, Garnier-Flammarion, 1992 * Épictète, ''Entretiens'', traduction J. Souilhé, Les Belles Lettres, 1943-1965 * Kant, E., ''Critique de la raison pure'', traduction A. Tremesaygues et B. Pacaud, PUF, 1944 * Leibniz, G.W., ''Nouveaux essais sur l'entendement humain'', édition J. Brunschwig, Garnier-Flammarion, 1990 * Locke, J., ''Essai sur l'entendement humain'', traduction J.-M. Vienne, Vrin, 2001 * Platon, ''Théétète'', traduction M. Narcy, Garnier-Flammarion, 1995 * Popper, K., ''La Logique de la découverte scientifique'', traduction N. Thyssen-Rutten et P. Devaux, Payot, 1973 * Popper, K., ''Conjectures et réfutations'', traduction M.-I. et M.B. de Launay, Payot, 1985 * Spinoza, B., ''Éthique'', traduction B. Pautrat, Seuil, 1999 * Thomas d'Aquin, ''Somme théologique'', traduction A.-M. Roguet, Cerf, 1984-1986 === Études secondaires === * BonJour, L., ''Epistemology: Classic Problems and Contemporary Responses'', Rowman & Littlefield, 2002 * Engel, P., ''La Vérité. Réflexions sur quelques truismes'', Hatier, 1998 * Gilson, É., ''René Descartes. Discours de la méthode, texte et commentaire'', Vrin, 1925 * Hadot, P., ''Qu'est-ce que la philosophie antique ?'', Gallimard, 1995 * Kahneman, D., ''Système 1, Système 2 : Les deux vitesses de la pensée'', traduction R. Clarinard, Flammarion, 2012 * Lecourt, D., ''L'épistémologie historique de Gaston Bachelard'', Vrin, 1969 * Long, A.A. et Sedley, D.N., ''Les Philosophes hellénistiques'', traduction J. Brunschwig et P. Pellegrin, Garnier-Flammarion, 2001, 3 volumes * Marion, J.-L., ''Sur la pensée passive de Descartes'', PUF, 2013 * Nadler, S., ''Spinoza's Ethics: An Introduction'', Cambridge University Press, 2006 * Popkin, R.H., ''Histoire du scepticisme d'Érasme à Spinoza'', traduction C. Hivet, PUF, 1995 * Prigogine, I. et Stengers, I., ''La Nouvelle Alliance. Métamorphose de la science'', Gallimard, 1979 * Sosa, E., ''Epistemology'', Princeton University Press, 2017 {{AutoCat}} [[Catégorie:Épistémologie]] [[Catégorie:Logique]] 34e0d22ynfl7tx6090zuyzxwrzw8qlz Python pour le calcul scientifique/Annexe/Index 0 83349 768479 767661 2026-06-24T10:41:47Z Cdang 1202 /* A */ and 768479 wikitext text/x-wiki {{SommaireCompact}} == * == * <code>+</code> (plus) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>+=</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>-</code> (moins) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|3]] * <code>-=</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>*</code> (astérisque) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>**</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>/</code> (barre de fraction) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>//</code> (barre de fraction) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>^</code> (circonflexe) : [[../../Découverte_de_Python_et_de_Jupyter#cite_note-2|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>&</code> (esperluette) : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>&=</code> : [[../../Découverte de Python et de Jupyter#Les booléens|1]] * <code>|</code> (tube) : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>|=</code> : [[../../Découverte de Python et de Jupyter#Les booléens|1]] == A == * <code>plt.add_subplot()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>axis.add_patch()</code> : [[../../Graphiques#Dessins|1]] * aléatoire (générateur de nombres pseudo-~) : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Graphiques|2]], [[../../Polynômes#Régression polynomiale|3]], [[../../Statistiques#Fréquence, histogramme|'''4''']], [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|5]], [[../../Régression et optimisation#Régression linéaire|6]] * <code>and</code> : [[../../Découverte_de_Python_et_de_Jupyter#Les_booléens|1]], [[../../Fonctions_mathématiques_générales#Fonctions_booléennes|2]] <br />voir [[#*|&]], [[#L|np.logical-all()]] * <code>all</code> : [[../../Fonctions_mathématiques_générales#Fonctions_booléennes|1]] * <code>axes.annotate()</code> : [[../../Graphiques#Annotations|1]] * <code>np.arange()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Premier_tracé_graphique|1]], [[../../Éléments_de_programmation#Définition_en_compréhension|2]], [[../../Graphiques|3]], [[../../Manipulation_de_matrices#Définir_un_tenseur|'''3''']]<br /> → [[#R|<code>range()</code>]] * <code>np.array()</code> (classe <code>ndarray</code>) : [[../../Fonctions_mathématiques_générales#Vecteurs_et_matrices|1]], [[../../Éléments_de_programmation#Exploiter_le_contenu_d'un_fichier_texte|2]], [[../../Graphiques#Transformation_des_objets_graphiques|3]], [[../../Manipulation_de_matrices|'''4''']], [[../../Statistiques#Méthodes_de_matrices|5]], [[../../Algèbre_linéaire#Opérations_vectorielles|6]] * <code>float.as_integer_ratio()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]], [[../../Éléments_de_programmation#Réels|2]] * <code>fig.axes</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] == B == * <code>plt.bar()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] * booléens : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Fonctions mathématiques générales#Fonctions booléennes|2]] * <code>break()</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == C == * ''{{lang|en|callable}}'' (« appelable ») : [[../../Découverte_de_Python_et_de_Jupyter#Appelable_(callable)|1]] * <code>str.capitalize()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.center()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>chr()</code> : [[../../Éléments_de_programmation#Autres_fonctions|1]] * classe (d'un langage orienté objet) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * <code>color</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>fig.colorbar()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * complexe (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>plt.contour()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>plt.contourf()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>continue()</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == D == * <code>def</code> : [[../../Éléments_de_programmation#Fonction|1]] * division euclidienne : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>divmode()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * <code>dpi</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] == E == * <code>edgecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>elif</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * <code>else</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * espace de nom (<code>np.</code>, <code>plt.</code>, <code>scipy.</code>…) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]], [[../../Découverte_de_Python_et_de_Jupyter#Les_espaces_de_noms|2]] == F == * <code>facecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>figsize</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>fillstyle</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>str.find()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * fonction (définir une ~) : [[../../Éléments_de_programmation#Fonction|1]] * <code>for</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == G == * <code>plt.gca()</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] * <code>plt.gcf()</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] * GIF animé : [[../../Graphiques#Créer_un_GIF_animé|1]] == H == * <code>plt.hist()</code> : [[../../Graphiques|1]] * <code>html</code> (module) : [[../../Découverte_de_Python_et_de_Jupyter#Les_chaînes_de_caractères|1]], [[../../Éléments_de_programmation#Autres_fonctions|2]] == I == * <code>if</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * imaginaire (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>in</code> : [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|1]], [[../../Éléments de programmation#Définition en compréhension|2]] * infini +∞, <code>float("inf")</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * instance (d'une classe) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * installation d'un module : [[../../Découverte de Python et de Jupyter#Installation et mise à jour de modules|1]] * <code>str.isdigit()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>float.is_integer()</code> : [[../../Éléments_de_programmation#Réels|1]] == J == * <code>j</code> (imaginaire) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] == L == * LaTeX : [[../../Graphiques#Mise_en_forme_du_texte|1]] * <code>layout</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>plt.legend()</code> : [[../../Graphiques|1]], [[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|2]] * <code>linear</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>linestyle</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>linewidth</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>str.ljust()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>log</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>logit</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>str.lower()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>ls</code> (paramètre) : voir ''linestyle'' * <code>lw</code> (paramètre) : voir ''linewidth'' == M == * <code>marker</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markeredgecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markeredgewidth</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markerfacecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markersize</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * Matplotlib (module, <code>np</code>) : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]], [[../../Graphiques|2]]<br />→ Pyplot * <code>np.meshgrid()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * méthode (d'une classe) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * module : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] == N == * NaN ''(not a number)'', <code>float("nan")</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * <code>nextafter()</code> : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]] * <code>normal()</code> [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|5]] * <code>np.</code> : espace de nom, abréviation de <code>numpy.</code><br />→ Numpy * Numpy (module) : [[../../Découverte de Python et de Jupyter|1]] == P == * <code>str.partition()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * ''patch'' (pièce, dessin) : [[../../Graphiques#Dessins|1]] * <code>plt.pcolormesh()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>pip install</code> : [[../../Découverte de Python et de Jupyter#Installation et mise à jour de modules|1]] * PIL (module ''Python imaging library'') : [[../../Graphiques#Créer_un_GIF_animé|1]] * <code>plt.plot()</code> : [[../../Graphiques|1]] * <code>plt.plot_surface()</code> : [[../../Graphiques#Surfaces_3D|1]] * <code>plt</code> : espace de nom, abréviation de <code>pyplot.</code><br />→ <code>plt</code> * <code>plt.polar()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>pow()</code> : [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|1]] * puissance (élévation à la) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>pyplot</code> (<code>plt</code>, option de Matplotlib) : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]], [[../../Graphiques|2]] * PyQt (module) : [[../../Éléments_de_programmation#Avec_PyQt|1]] == Q == * <code>plt.quiver()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] == R == * <code>rand()</code> : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Statistiques#Fréquence, histogramme|'''2''']] * <code>randn()</code> : [[../../Graphiques|1]], [[../../Polynômes#Régression polynomiale|2]], [[../../Statistiques#Fréquence, histogramme|'''3''']], [[../../Régression et optimisation#Régression linéaire|4]] * <code>random</code> (module NumPy) : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Statistiques#Fréquence, histogramme|'''2''']], [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|3]] * <code>range()</code> : [[../../Premiers programmes#Deuxième_programme|1]], [[../../Éléments_de_programmation#Autres_fonctions|2]], [[../../Éléments_de_programmation#Définition_en_compréhension|3]], [[../../Éléments_de_programmation#Structures_de_contrôle|4]]<br /> → [[#A|<code>np.arange()</code>]] * <code>plt.rcParams()</code> : [[../../Graphiques#Mise_en_forme_du_texte|1]] * réel à virgule flottante (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>str.replace()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.rfind()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.rjust()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] == S == * <code>plt.savefig()</code> : [[../../Graphiques#Exemple|1]] * <code>line2D.set()</code>[[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|1]] * <code>axis.set_aspect()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>line2D.set_label()</code>[[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|1]] * <code>line2D.set_linestyle()</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>axes.set_rticks()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>axes.set_thetagrids()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>axes.set_title()</code> : [[../../Graphiques#Exemple|1]] * <code>axes.set_xlabel()</code> : [[../../Graphiques#Exemple|1]] * <code>axis.set_xlim()</code> : [[../../Graphiques#Dessins|1]] * <code>axis.set_xsticks()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>axes.set_ylabel()</code> : [[../../Graphiques#Exemple|1]] * <code>axis.set_ylim()</code> : [[../../Graphiques#Dessins|1]] * <code>axis.set_minor_formatter()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * ''shebang'' : [[../../Découverte de Python et de Jupyter|1]] * <code>plt.show()</code> : [[../../Graphiques|1]] * <code>str.split()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>plt.step()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] * <code>plt.subplots()</code> : [[../../Graphiques#Exemple|1]] * <code>fig.suptitle()</code> : [[../../Graphiques#Exemple|1]] * <code>plt.suptitle()</code> : [[../../Graphiques#Exemple|1]] * <code>symlog</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] == T == * <code>plt.text()</code> : [[../../Graphiques#Annotations|1]] * <code>plt.title()</code> : [[../../Graphiques|1]] * <code>aix.transData()</code> : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * <code>transform</code> (paramètre) : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * <code>matplotlib.transforms()</code> : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * Tk (module) : [[../../Éléments_de_programmation#Avec_Tk|1]] == U == * <code>str.upper()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] == W == * <code>while</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == X == * <code>plt.xlabel()</code> : [[../../Graphiques|1]] == Y == * <code>plt.ylabel()</code> : [[../../Graphiques|1]] ---- [[../../Traitement d'images|Traitement d'images]] &lt; [[../../|↑]] &gt; [[Catégorie:Python pour le calcul scientifique (livre)]] k7yax8g9mb0c0cmzoeovuj6w80rzboe 768480 768479 2026-06-24T10:42:39Z Cdang 1202 /* L */ np.logical_and() 768480 wikitext text/x-wiki {{SommaireCompact}} == * == * <code>+</code> (plus) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>+=</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>-</code> (moins) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|3]] * <code>-=</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>*</code> (astérisque) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>**</code> : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>/</code> (barre de fraction) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>//</code> (barre de fraction) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>^</code> (circonflexe) : [[../../Découverte_de_Python_et_de_Jupyter#cite_note-2|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>&</code> (esperluette) : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>&=</code> : [[../../Découverte de Python et de Jupyter#Les booléens|1]] * <code>|</code> (tube) : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|2]] * <code>|=</code> : [[../../Découverte de Python et de Jupyter#Les booléens|1]] == A == * <code>plt.add_subplot()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>axis.add_patch()</code> : [[../../Graphiques#Dessins|1]] * aléatoire (générateur de nombres pseudo-~) : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Graphiques|2]], [[../../Polynômes#Régression polynomiale|3]], [[../../Statistiques#Fréquence, histogramme|'''4''']], [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|5]], [[../../Régression et optimisation#Régression linéaire|6]] * <code>and</code> : [[../../Découverte_de_Python_et_de_Jupyter#Les_booléens|1]], [[../../Fonctions_mathématiques_générales#Fonctions_booléennes|2]] <br />voir [[#*|&]], [[#L|np.logical-all()]] * <code>all</code> : [[../../Fonctions_mathématiques_générales#Fonctions_booléennes|1]] * <code>axes.annotate()</code> : [[../../Graphiques#Annotations|1]] * <code>np.arange()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Premier_tracé_graphique|1]], [[../../Éléments_de_programmation#Définition_en_compréhension|2]], [[../../Graphiques|3]], [[../../Manipulation_de_matrices#Définir_un_tenseur|'''3''']]<br /> → [[#R|<code>range()</code>]] * <code>np.array()</code> (classe <code>ndarray</code>) : [[../../Fonctions_mathématiques_générales#Vecteurs_et_matrices|1]], [[../../Éléments_de_programmation#Exploiter_le_contenu_d'un_fichier_texte|2]], [[../../Graphiques#Transformation_des_objets_graphiques|3]], [[../../Manipulation_de_matrices|'''4''']], [[../../Statistiques#Méthodes_de_matrices|5]], [[../../Algèbre_linéaire#Opérations_vectorielles|6]] * <code>float.as_integer_ratio()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]], [[../../Éléments_de_programmation#Réels|2]] * <code>fig.axes</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] == B == * <code>plt.bar()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] * booléens : [[../../Découverte de Python et de Jupyter#Les booléens|1]], [[../../Fonctions mathématiques générales#Fonctions booléennes|2]] * <code>break()</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == C == * ''{{lang|en|callable}}'' (« appelable ») : [[../../Découverte_de_Python_et_de_Jupyter#Appelable_(callable)|1]] * <code>str.capitalize()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.center()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>chr()</code> : [[../../Éléments_de_programmation#Autres_fonctions|1]] * classe (d'un langage orienté objet) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * <code>color</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>fig.colorbar()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * complexe (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>plt.contour()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>plt.contourf()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>continue()</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == D == * <code>def</code> : [[../../Éléments_de_programmation#Fonction|1]] * division euclidienne : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>divmode()</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * <code>dpi</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] == E == * <code>edgecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>elif</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * <code>else</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * espace de nom (<code>np.</code>, <code>plt.</code>, <code>scipy.</code>…) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]], [[../../Découverte_de_Python_et_de_Jupyter#Les_espaces_de_noms|2]] == F == * <code>facecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>figsize</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>fillstyle</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>str.find()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * fonction (définir une ~) : [[../../Éléments_de_programmation#Fonction|1]] * <code>for</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == G == * <code>plt.gca()</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] * <code>plt.gcf()</code> : [[../../Graphiques#Styles_de_codage_«_pyplot_»_et_«_OO_»|1]] * GIF animé : [[../../Graphiques#Créer_un_GIF_animé|1]] == H == * <code>plt.hist()</code> : [[../../Graphiques|1]] * <code>html</code> (module) : [[../../Découverte_de_Python_et_de_Jupyter#Les_chaînes_de_caractères|1]], [[../../Éléments_de_programmation#Autres_fonctions|2]] == I == * <code>if</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] * imaginaire (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>in</code> : [[../../Découverte de Python et de Jupyter#Les ensembles et les dictionnaires|1]], [[../../Éléments de programmation#Définition en compréhension|2]] * infini +∞, <code>float("inf")</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * instance (d'une classe) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * installation d'un module : [[../../Découverte de Python et de Jupyter#Installation et mise à jour de modules|1]] * <code>str.isdigit()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>float.is_integer()</code> : [[../../Éléments_de_programmation#Réels|1]] == J == * <code>j</code> (imaginaire) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] == L == * LaTeX : [[../../Graphiques#Mise_en_forme_du_texte|1]] * <code>layout</code> (paramètre) : [[../../Graphiques#Mise_en_forme_de_la_figure|1]] * <code>plt.legend()</code> : [[../../Graphiques|1]], [[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|2]] * <code>linear</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>linestyle</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>linewidth</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>str.ljust()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>log</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>np.logical_and()</code> : [[../../Fonctions_mathématiques_générales#Fonctions_booléennes|1]]<br /> voir [[#A|and]] * <code>logit</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>str.lower()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>ls</code> (paramètre) : voir ''linestyle'' * <code>lw</code> (paramètre) : voir ''linewidth'' == M == * <code>marker</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markeredgecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markeredgewidth</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markerfacecolor</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>markersize</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * Matplotlib (module, <code>np</code>) : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]], [[../../Graphiques|2]]<br />→ Pyplot * <code>np.meshgrid()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * méthode (d'une classe) : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] * module : [[../../Découverte_de_Python_et_de_Jupyter#Vocabulaire|1]] == N == * NaN ''(not a number)'', <code>float("nan")</code> : [[../../Découverte_de_Python_et_de_Jupyter#Commandes_élémentaires|1]] * <code>nextafter()</code> : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]] * <code>normal()</code> [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|5]] * <code>np.</code> : espace de nom, abréviation de <code>numpy.</code><br />→ Numpy * Numpy (module) : [[../../Découverte de Python et de Jupyter|1]] == P == * <code>str.partition()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * ''patch'' (pièce, dessin) : [[../../Graphiques#Dessins|1]] * <code>plt.pcolormesh()</code> : [[../../Graphiques#Cartes_de_valeurs_et_de_vecteurs|1]] * <code>pip install</code> : [[../../Découverte de Python et de Jupyter#Installation et mise à jour de modules|1]] * PIL (module ''Python imaging library'') : [[../../Graphiques#Créer_un_GIF_animé|1]] * <code>plt.plot()</code> : [[../../Graphiques|1]] * <code>plt.plot_surface()</code> : [[../../Graphiques#Surfaces_3D|1]] * <code>plt</code> : espace de nom, abréviation de <code>pyplot.</code><br />→ <code>plt</code> * <code>plt.polar()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>pow()</code> : [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|1]] * puissance (élévation à la) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]], [[../../Fonctions mathématiques générales#Rappel sur les opérations de base|2]] * <code>pyplot</code> (<code>plt</code>, option de Matplotlib) : [[../../Découverte de Python et de Jupyter#Premier tracé graphique|1]], [[../../Graphiques|2]] * PyQt (module) : [[../../Éléments_de_programmation#Avec_PyQt|1]] == Q == * <code>plt.quiver()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] == R == * <code>rand()</code> : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Statistiques#Fréquence, histogramme|'''2''']] * <code>randn()</code> : [[../../Graphiques|1]], [[../../Polynômes#Régression polynomiale|2]], [[../../Statistiques#Fréquence, histogramme|'''3''']], [[../../Régression et optimisation#Régression linéaire|4]] * <code>random</code> (module NumPy) : [[../../Éléments de programmation#Utilisation de Pandas|1]], [[../../Statistiques#Fréquence, histogramme|'''2''']], [[../../Interpolation, extrapolation et lissage#Avec le module scipy.signal|3]] * <code>range()</code> : [[../../Premiers programmes#Deuxième_programme|1]], [[../../Éléments_de_programmation#Autres_fonctions|2]], [[../../Éléments_de_programmation#Définition_en_compréhension|3]], [[../../Éléments_de_programmation#Structures_de_contrôle|4]]<br /> → [[#A|<code>np.arange()</code>]] * <code>plt.rcParams()</code> : [[../../Graphiques#Mise_en_forme_du_texte|1]] * réel à virgule flottante (nombre) : [[../../Découverte de Python et de Jupyter#Commandes élémentaires|1]] * <code>str.replace()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.rfind()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>str.rjust()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] == S == * <code>plt.savefig()</code> : [[../../Graphiques#Exemple|1]] * <code>line2D.set()</code>[[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|1]] * <code>axis.set_aspect()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>line2D.set_label()</code>[[../../Graphiques#Plusieurs_courbes_sur_un_même_système_d'axes|1]] * <code>line2D.set_linestyle()</code> (paramètre) : [[../../Graphiques#Mise_en_forme_d'une_courbe|1]] * <code>axes.set_rticks()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>axes.set_thetagrids()</code> : [[../../Graphiques#Tracé_polaire|1]] * <code>axes.set_title()</code> : [[../../Graphiques#Exemple|1]] * <code>axes.set_xlabel()</code> : [[../../Graphiques#Exemple|1]] * <code>axis.set_xlim()</code> : [[../../Graphiques#Dessins|1]] * <code>axis.set_xsticks()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * <code>axes.set_ylabel()</code> : [[../../Graphiques#Exemple|1]] * <code>axis.set_ylim()</code> : [[../../Graphiques#Dessins|1]] * <code>axis.set_minor_formatter()</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] * ''shebang'' : [[../../Découverte de Python et de Jupyter|1]] * <code>plt.show()</code> : [[../../Graphiques|1]] * <code>str.split()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] * <code>plt.step()</code> : [[../../Graphiques#Autres_exemples_de_tracés_2D|1]] * <code>plt.subplots()</code> : [[../../Graphiques#Exemple|1]] * <code>fig.suptitle()</code> : [[../../Graphiques#Exemple|1]] * <code>plt.suptitle()</code> : [[../../Graphiques#Exemple|1]] * <code>symlog</code> (paramètre) : [[../../Graphiques#Gestion_des_échelles|1]] == T == * <code>plt.text()</code> : [[../../Graphiques#Annotations|1]] * <code>plt.title()</code> : [[../../Graphiques|1]] * <code>aix.transData()</code> : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * <code>transform</code> (paramètre) : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * <code>matplotlib.transforms()</code> : [[../../Graphiques#Transformation_des_objets_graphiques|1]] * Tk (module) : [[../../Éléments_de_programmation#Avec_Tk|1]] == U == * <code>str.upper()</code> : [[../../Éléments_de_programmation#Méthodes_des_chaînes|1]] == W == * <code>while</code> : [[../../Éléments_de_programmation#Structures_de_contrôle|1]] == X == * <code>plt.xlabel()</code> : [[../../Graphiques|1]] == Y == * <code>plt.ylabel()</code> : [[../../Graphiques|1]] ---- [[../../Traitement d'images|Traitement d'images]] &lt; [[../../|↑]] &gt; [[Catégorie:Python pour le calcul scientifique (livre)]] 4a6t1id9nxwlyvnkcvy5qtgzdcj90v4 Discussion Wikilivres:Le Bistro/2026 5 83406 768401 767795 2026-06-23T13:05:07Z MediaWiki message delivery 36013 /* Actualités techniques n° 2026-26 */ nouvelle section 768401 wikitext text/x-wiki == Actualités techniques n° 2026-03 == <section begin="technews-2026-W03"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/03|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * La Fondation Wikimedia a publié des questions directrices pour son plan annuel de juillet 2026 à juin 2027 sur les plateformes [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] et ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. Celles-ci portent sur les tendances mondiales, une expérimentation plus rapide et plus constructive, un meilleur accompagnement des nouveaux contributeurs, le renforcement du rôle des éditeurs et des utilisateurs avancés, l'amélioration de la collaboration entre les projets, ainsi que le développement et la fidélisation du lectorat. Des commentaires et suggestions sont les bienvenus sur la [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|page de discussion]]. '''Actualités pour la contribution''' * Dans le cadre des travaux en cours de l'équipe technique communautaire sur le projet [[m:Special:MyLanguage/Community Wishlist/W372|Listes de surveillance multiples]], l'affichage de [[Special:EditWatchlist|Modifier la liste de surveillance]] sera mis à jour entant que qu'une première étape vers la prise en charge de plusieurs listes de surveillance. De plus, la pagination de [[Special:Search|Recherche]] sera également mise à jour, dans le cadre du travail sur le souhait [[m:Special:MyLanguage/Community Wishlist/W186|Refonte de la pagination / navigation des pages]]. [https://phabricator.wikimedia.org/T411596] * [[m:Special:GlobalWatchlist|La Liste de Surveillance Globale]] est une [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] de MediaWiki qui vous permet de voir vos listes de surveillance provenant de différents wikis sur la même page. Il a récemment été mis à jour pour ressembler davantage à la [[Special:Watchlist|Liste de surveillance]] régulière, par exemple en le préparant pour les comptes temporaires dans le masquage IP (y compris le réacheminement des liens des utilisateurs vers les pages de contributions), en mettant les titres de page en gras et en ouvrant les liens dans les résumés d'édition et les balises dans de nouveaux onglets du navigateur. [https://phabricator.wikimedia.org/T398361][https://phabricator.wikimedia.org/T298919][https://phabricator.wikimedia.org/T273526][https://phabricator.wikimedia.org/T286309] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:28|la tâche soumise|les {{formatnum:28}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:28||s}} la semaine dernière]]. Par exemple, le problème selon lequel les blocs globaux ne disposaient pas de l'option permettant de désactiver l'envoi d'e-mails a maintenant été résolu et sera disponible à l'utilisation à partir de la semaine du 13 janvier. [https://phabricator.wikimedia.org/T401293] '''Actualités pour la contribution technique''' * L'[[mw:Special:MyLanguage/VisualEditor/Citation tool|outil de citation VisualEditor]] et les [[mw:Special:MyLanguage/Help:Reference Previews|Aperçus de référence]] prennent désormais en charge "carte" comme type de référence. [https://phabricator.wikimedia.org/T411083] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.10|MediaWiki]]/[[mw:MediaWiki 1.46/wmf.11|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/03|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W03"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 12 janvier 2026 à 20:33 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29907192 --> == Thank You for Last Year – Join Wiki Loves Ramadan 2026 == Dear Wikimedia communities, We hope you are doing well, and we wish you a happy New Year. ''Last year, we captured light. This year, we’ll capture legacy.'' In 2025, communities around the world shared the glow of Ramadan nights and the warmth of collective iftars. In 2026, ''Wiki Loves Ramadan'' is expanding, bringing more stories, more cultures, and deeper global connections across Wikimedia projects. We invite you to explore the ''Wiki Loves Ramadan 2026'' [[m:Special:MyLanguage/Wiki Loves Ramadan 2026|Meta page]] to learn how you can participate and [[m:Special:MyLanguage/Wiki Loves Ramadan 2026/Participating communities|sign up]] your community. 📷 ''Photo campaign on '' [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan 2026|Wikimedia Commons]] If you have questions about the project, please refer to the FAQs: * [[m:Special:MyLanguage/Wiki Loves Ramadan/FAQ/|Meta-Wiki]] * [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan/FAQ|Wikimedia Commons]] ''Early registration for updates is now open via the '''[[m:Special:RegisterForEvent/2710|Event page]]''''' ''Stay connected and receive updates:'' * [https://t.me/WikiLovesRamadan Telegram channel] * [https://lists.wikimedia.org/postorius/lists/wikilovesramadan.lists.wikimedia.org/ Mailing list] We look forward to collaborating with you and your community. '''The Wiki Loves Ramadan 2026 Organizing Team''' 16 janvier 2026 à 20:44 (CET) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29879549 --> == <span lang="en" dir="ltr">Tech News: 2026-04</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W04"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/04|Translations]] are available. '''Updates for editors''' * The tray shown on [[Special:Diff|Special:Diff]] in mobile view has been redesigned. It is now collapsed by default, and incorporates a link to undo the edit being viewed, making it easier for mobile editors and reviewers to take action while keeping the interface uncluttered. [https://phabricator.wikimedia.org/T402297] * [[m:Special:GlobalWatchlist|The Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continues to improve — it now automatically determines the text direction (ensuring correct display of sites with unusual domain names) and shows detailed descriptions for log actions. Later this week, a new permanent link for page creations and CSS classes for each entry element will be added. [https://phabricator.wikimedia.org/T412505][https://phabricator.wikimedia.org/T287929][https://phabricator.wikimedia.org/T262768][https://phabricator.wikimedia.org/T414135] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:32}} community-submitted {{PLURAL:32|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the previously observed issue in Vector 2022, where anchor link targets were obscured by the sticky header, has now been addressed. [https://phabricator.wikimedia.org/T406114] '''Updates for technical contributors''' * As mentioned in the [[m:Special:MyLanguage/Tech/News/2025/44|October 2025 deprecation announcement]], MediaWiki Interfaces team will begin sunsetting all transform endpoints containing a trailing slash from the MediaWiki REST API the week of January 26. Changes are expected to roll out to all wikis on or before January 30th. All API users currently calling them are encouraged to transition to the non-trailing slash versions. Both endpoint variations can be found, compared, and tested using the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox]. If you have questions or encounter any problems, please file a ticket in Phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * Interactive reference documentation for the [[mw:Special:MyLanguage/Wikimedia REST API|Wikimedia REST API]] has moved. Requests to API docs previously hosted through [[mw:Special:MyLanguage/RESTBase|RESTBase]] (e.g.: <code dir=ltr>https://en.wikipedia.org/api/rest_v1/</code>) are now redirected to the [[w:en:Special:RestSandbox|REST Sandbox]]. * The [[mw:Special:MyLanguage/Wikidata Platform|WMF Wikidata Platform team]] (WDP) has published its [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|January 2026 newsletter]]. It includes updates on the legacy full-graph endpoint decommissioning, the User-Agent policy change, the monthly Blazegraph migration office hours, and efforts to reduce regressions caused by the legacy endpoint shutdown. As a reminder, you can [[m:Special:MyLanguage/Global message delivery/Targets/WDP team updates|subscribe to the WDP newsletter]]! * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.12|MediaWiki]] '''Meetings and events''' * The [[mw:Wikimedia Hackathon Northwestern Europe 2026|Wikimedia Hackathon Northwestern Europe 2026]] will take place on 13-14 March 2026 in Arnhem, the Netherlands. Applications opened mid-December and will close soon or when capacity is reached. It's a two-day, technically oriented hackathon bringing together Wikimedians from the region. Hope to see you there! '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/04|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W04"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 19 janvier 2026 à 21:29 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29943403 --> == Révision annuelle du code universel de conduite et des lignes directrices de l'application == <section begin="announcement-content" /> Nous vous informons que la période de relecture annuelle du Code de conduite universel et des règles d'applications est actuellement ouverte. Vous pouvez faire vos commentaires sur les modifications que vous souhaitez apporter jusqu'au 9 février 2026. C'est la première d'une série d'étapes nécessaires pour la révision annuelle. Vous trouverez [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|d'autres informations et les discussions auxquelles participer sur la page UCoC de Meta]]. Le [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Comité de coordination du code universel de conduite]] (U4C &mdash; Universal Code of Conduct Coordinating Committee) est un groupe global dont le rôle est de fournir une implémentation équitable et cohérente de l'UCoC. Cette relecture annuelle a été envisagée et mise en place par l'U4C. Pour plus d'informations et les responsabilités de l'U4C, veuillez lire la [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|Charte de l'U4C]]. Veuillez partager ces informations avec les autres membres concernés de votre communauté. -- En coopération avec l'U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|discussion]])<section end="announcement-content" /> 19 janvier 2026 à 22:01 (CET) <!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == Actualités techniques n° 2026-05 == <section begin="technews-2026-W05"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/05|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * La Fondation Wikimedia invite à donner des commentaires sur [[m:Special:MyLanguage/Product and Technology Advisory Council/Year1 Reflections and Proposed Way Forward 2026 Update|l’avenir proposé]] du [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif des produits et technologies]] jusqu’au 28 février. * Tous les utilisateurs disposant d'un compte enregistré peuvent désormais utiliser des clés d'accès pour la [[m:Special:MyLanguage/Help:Two-factor authentication|double authentification]] (2FA). Les clés d'accès sont un moyen simple de se connecter sans utiliser un second appareil. Elles vérifient l'identité de l'utilisateur à l'aide d'une empreinte digitale, d'une reconnaissance faciale ou d'un code PIN. Pour configurer une clé d'accès, configurez d'abord une méthode 2FA classique. Actuellement, pour se connecter avec une clé d'accès, les utilisateurs doivent également utiliser un mot de passe. Plus tard ce trimestre, la connexion sans mot de passe permettra aux utilisateurs de se connecter d'un simple clic avec une clé d'accès. Les utilisateurs disposant de droits avancés devront également avoir la 2FA activée. Cela fait partie du projet [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security|Sécurité du compte]]. * Les contributeurs non enregistrés sur des IP bloquées ou des plages d'IP bloquées peuvent désormais interagir sur le wiki pour faire appel d'un blocage en créant un compte temporaire afin de contester un blocage sur la page de discussion de l'utilisateur, sauf si l'option « empêcher cet utilisateur de modifier sa propre page de discussion » est activée. Cela résout le problème des utilisateurs déconnectés incapables d'utiliser le processus de déblocage par défaut via la page de discussion de l'utilisateur. [https://phabricator.wikimedia.org/T398673] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:20|la tâche soumise|les {{formatnum:20}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:20||s}} la semaine dernière]]. Par exemple, la description des méthodes d'authentification à deux facteurs (2FA) sur la page de gestion a été mise à jour. Il est désormais plus clair et plus facile pour les utilisateurs à comprendre et à utiliser. [https://phabricator.wikimedia.org/T332385] '''Actualités pour la contribution technique''' * Une nouvelle variable AbuseFilter, <code>account_type</code>, a été ajoutée pour fournir un moyen fiable de déterminer le type de compte créé dans les actions <code>createaccount</code> et <code>autocreateaccount</code>. Dans le cadre de ce changement, la variable <code>accountname</code> a été renommée en <code>account_name</code>, et <code>accountname</code> est désormais obsolète. Les gestionnaires de filtres doivent mettre à jour tous les filtres qui utilisent des vérifications de type de compte codées en dur ou la variable obsolète. [https://phabricator.wikimedia.org/T414049] * Les vignettes d'images demandées dans des tailles non standard, et en utilisant des méthodes non standard telles que les requêtes directes à <code dir=ltr><nowiki>upload.wikimedia.org/…</nowiki></code>, cesseront de fonctionner dans un proche avenir. Ce changement vise à prévenir les abus externes continus par des robots et des aspirateurs web. Certains utilisateurs ayant des CSS/JS personnalisés, les administrateurs d'interface qui peuvent corriger les gadgets et les thèmes locaux, ainsi que les auteurs d'outils, devront mettre à jour leur code pour utiliser des tailles de vignettes standard. [[phab:T414805|Des détails, des liens de recherche et des exemples de correction sont disponibles dans la tâche]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.13|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/05|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W05"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 26 janvier 2026 à 22:17 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29969530 --> == <span lang="en" dir="ltr">Tech News: 2026-06</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W06"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/06|Translations]] are available. '''Updates for editors''' * The "{{int:pageinfo-toolboxlink}}" feature, which gives validating information about a page ([{{fullurl:{{FULLPAGENAME}}|action=info}} example]), now automatically includes a table of contents. If there is a local [[{{ns:8}}:Pageinfo-header]] page created by individual users, it can now be removed. [https://phabricator.wikimedia.org/T363726] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, VisualEditor previously added bold or italic formatting inside link descriptions, making the wikicode complex. This has now been fixed. [https://phabricator.wikimedia.org/T409669] '''Updates for technical contributors''' * There was no XML dump on 20 January. Additionally, from now on, dumps will be generated once per month only. [https://phabricator.wikimedia.org/T414389] * The MediaWiki Interfaces team removed support for all transform endpoints containing a trailing slash from the [https://www.mediawiki.org/wiki/Special:MyLanguage/API:REST%20API MediaWiki REST API]. All API users currently calling those endpoints are encouraged to transition to the non-trailing slash versions. If you have questions or encounter any problems, please file a ticket in phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.14|MediaWiki]] '''Weekly highlight''' * Users are reminded that the Wikimedia Foundation has shared some guiding questions for the July 2026–June 2027 Annual Plan on [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] and ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. These focus on global trends, faster and healthier experimentation, better support for newcomers, strengthening editors and advanced users, improving collaboration across projects, and growing and retaining readership. Feedback and ideas are welcome on the [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|talk page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/06|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W06"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 février 2026 à 18:43 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30000986 --> == Actualités techniques n° 2026-07 == <section begin="technews-2026-W07"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/07|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] Les contributeurs connectés qui gèrent de grandes ou complexes listes de suivi peuvent désormais organiser et filtrer les pages surveillées de manière à améliorer leurs flux de travail grâce à la nouvelle fonctionnalité [[mw:Special:MyLanguage/Help:Watchlist labels|Étiquettes de liste de suivi]]. En ajoutant des étiquettes personnalisées (par exemple : pages que vous avez créées, pages surveillées pour vandalisme, ou pages de discussion), les utilisateurs peuvent identifier plus rapidement ce qui nécessite une attention, réduire la charge cognitive et répondre plus efficacement. Cela améliore l'utilisabilité de la liste de suivi, en particulier pour les éditeurs très actifs. * Une nouvelle fonctionnalité disponible sur [[Special:Contributions|Special:Contributions]] montre [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts|des comptes temporaires]] qui sont probablement utilisés par la même personne, et rend ainsi le patrouillage moins chronophage. En vérifiant les contributions d'un compte temporaire, les utilisateurs ayant accès aux adresses IP des comptes temporaires peuvent désormais avoir une vue des contributions des comptes temporaires associés. La fonctionnalité recherche toutes les adresses IP associées à un compte temporaire donné pendant la période de conservation des données et affiche toutes les contributions de tous les comptes temporaires ayant utilisé ces adresses IP. [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts#February 2026: Improvements to the patroller tooling|Plus...]] [https://phabricator.wikimedia.org/T415674] * Lorsque les éditeurs prévisualisent une modification de wikitexte, la boîte de rappel indiquant qu'ils ne voient qu'une prévisualisation (qui est affichée en haut) a désormais un fond gris/neutre au lieu d'un fond jaune/d'avertissement. Cela facilite la distinction entre les notes de prévisualisation et les avertissements réels (par exemple, les conflits de modification ou les cibles de redirection problématiques), qui seront désormais affichés dans des boîtes d'avertissement ou d'erreur séparées. [https://phabricator.wikimedia.org/T414742] * La [[m:Special:GlobalWatchlist|Liste de suivi globale]] vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page. L' [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continue de s'améliorer — elle prend désormais en charge correctement plus d'un site Wikibase, par exemple à la fois [[d:|Wikidata]] et [[testwikidata:|testwikidata]]. De plus, des problèmes concernant la direction du texte ont été résolus pour les utilisateurs qui préfèrent Wikidata ou d'autres sites Wikibase dans des langues de droite à gauche (RTL). [https://phabricator.wikimedia.org/T415440][https://phabricator.wikimedia.org/T415458] * <span lang="en" dir="ltr" class="mw-content-ltr">The automatic "magic links" for ISBN, RFC, and PMID numbers have been [[mw:Special:MyLanguage/Help:Magic links|deprecated in wikitext since 2021]] due to inflexibility and difficulties with localization. Several wikis have successfully replaced RFC and PMID magic links with equivalent external links, but a template was often required to replace the functionality of the ISBN magic link. There is now a new [[mw:Special:MyLanguage/Help:Magic words#isbn|built-in parser function]] <code dir=ltr><nowiki>{{#isbn}}</nowiki></code> available to replace the basic functionality of the ISBN magic link. This makes it easier for wikis who wish to migrate off of the deprecated magic link functionality to do so.</span> [https://phabricator.wikimedia.org/T145604] * Deux nouveaux wikis ont été créés : ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q35401|Jju]] ([[w:kaj:|<code>w:kaj:</code>]]) [https://phabricator.wikimedia.org/T413283] ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q1186896|Nawat]] ([[w:ppl:|<code>w:ppl:</code>]]) [https://phabricator.wikimedia.org/T413273] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * Un nouveau groupe d'utilisateurs global a été créé : [[{{int:grouppage-local-bot}}|{{int:group-local-bot}}]]. Il sera utilisé en interne par le logiciel pour permettre aux robots communautaires de contourner les limites de débit appliquées aux [[w:en:Web_scraping|web scrapers]] abusifs. Les comptes approuvés en tant que robots sur au moins un wiki Wikimedia seront automatiquement ajoutés à ce groupe. Cela ne changera pas les autorisations dont dispose le robot. [https://phabricator.wikimedia.org/T415588] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.15|MediaWiki]] '''Rencontres et évènements''' * La [[mw:Special:MyLanguage/MediaWiki Users and Developers Conference Spring 2026|Conférence des utilisateurs et des développeurs de MediaWiki, Printemps 2026]] se tiendra du 25 au 27 mars à Salt Lake City, États-Unis. Cet événement est organisé par et pour la communauté MediaWiki de tiers. Vous pouvez proposer des sessions et vous inscrire pour y assister. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/AZBWVI46SDEB65PGR5J6E4TYOQQEZXM7/] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/07|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W07"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10 février 2026 à 00:30 (CET) <!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30026671 --> == Actualités techniques n° 2026-08 == <section begin="technews-2026-W08"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/08|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * <span class="mw-translate-fuzzy">L'[[mw:Special:MyLanguage/Wikimedia Site Reliability Engineering|équipe SRE]] va procéder au nettoyage d'[[m:Special:MyLanguage/Etherpad|Etherpad]], l'éditeur web open source de documents collaboratifs en temps réel. Tous les blocs-notes seront définitivement supprimés après le 30 avril 2026 – si des projets de migration sont encore en cours à cette date, l'équipe pourra réexaminer la date au cas par cas. Veuillez effectuer des sauvegardes locales de tout contenu que vous souhaitez conserver, car les données supprimées ne pourront pas être récupérées. Ce nettoyage permet de réduire la taille de la base de données et l'empreinte de l'infrastructure. Etherpad continuera de prendre en charge la collaboration en temps réel, mais le stockage à long terme n'est plus assuré. D'autres nettoyages pourront avoir lieu ultérieurement sans préavis.</span> [https://phabricator.wikimedia.org/T415237] '''Actualités pour la contribution''' * L'équipe de Recherche d'Informations lancera une [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|expérimentation sur l'application mobile Android]], afin de tester des fonctionnalités de recherche hybrides capables de gérer à la fois les requêtes sémantiques et par mots-clés. L'amélioration de la recherche sur la plateforme permettra aux lecteurs de trouver plus facilement ce qu'ils cherchent, directement sur Wikipédia. L'expérimentation sera d'abord lancée sur Wikipédia en grec fin février, puis sur les versions anglaise, française et portugaise en mars. [https://diff.wikimedia.org/2026/01/08/semantic-search-making-it-easier-to-find-the-information-readers-want/ En savoir plus] sur le blog ''Diff''. [https://www.mediawiki.org/wiki/Readers/Information_Retrieval] * L'équipe « Croissance des lecteurs » mènera [[mw:Special:MyLanguage/Readers/Reader Growth/WE3.10.2 Mobile Table of Contents|une expérience]] auprès des utilisateurs de la version mobile du site web qui ajoute une table des matières et développe automatiquement toutes les sections des articles, afin de mieux comprendre les problèmes de navigation qu'ils rencontrent. Le test sera disponible sur les versions arabe, chinoise, anglaise, française, indonésienne et vietnamienne de Wikipedia. * Auparavant, les notifications ([[{{ns:8}}:Sitenotice]] et [[{{ns:8}}:Anonnotice]]) du site ne s'affichaient que sur la version ordinateur. Maintenant, elles s'afficheront désormais sur toutes les plateformes. Les utilisateurs mobiles verront ces notifications. Les administrateurs du site doivent être prêts à tester et à corriger les notifications sur les appareils mobiles afin d'éviter toute interférence avec les articles. Pour désactiver ces notifications, les administrateurs d'interface peuvent ajouter <code dir="ltr">#siteNotice { display: none; }</code> à [[{{ns:8}}:Minerva.css]]. [https://phabricator.wikimedia.org/T138572][https://phabricator.wikimedia.org/T416644] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:19|la tâche soumise|les {{formatnum:19}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:19||s}} la semaine dernière]]. Par exemple, un problème concernant la section ''[[Special:RecentChanges|Spécial:Modifications récentes]]'' a été résolu. Auparavant, cliquer sur « Masquer » dans les filtres actifs entraînait la disparition du bouton « Afficher les nouvelles modifications depuis… », alors qu'il aurait dû rester visible. Ce bouton fonctionne désormais correctement. [https://phabricator.wikimedia.org/T406339] '''Actualités pour la contribution technique''' * Une nouvelle documentation est désormais disponible pour aider les rédacteurs à déboguer les fonctionnalités de recherche interne. Elle facilite le dépannage lorsque des pages n'apparaissent pas dans les résultats, lorsque le classement semble inattendu et lorsqu'il est nécessaire d'inspecter le contenu indexé, ce qui permet de mieux comprendre et d'analyser le comportement de la recherche. [[mw:Help:CirrusSearch/Debug|En savoir plus]]. [https://phabricator.wikimedia.org/T411169] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.16|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/08|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W08"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 février 2026 à 20:17 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30086330 --> == <span lang="en" dir="ltr">Tech News: 2026-09</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W09"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/09|Translations]] are available. '''Weekly highlight''' * [[mw:Special:MyLanguage/Edit check/Reference Check|Reference Check]] has been deployed to English Wikipedia, completing its rollout across all Wikipedias. The feature prompts newcomers to add a citation before publishing new content, helping reduce common citation-related reverts and improve verifiability. In A/B testing, the impact was substantial: newcomers shown Reference Check were approximately 2.2 times more likely to include a reference on desktop and about 17.5 times more likely on mobile web. [https://analytics.wikimedia.org/published/reports/editing/reference_check_ab_test_report_final_2025.html] '''Updates for editors''' * The [[mw:Special:MyLanguage/Extension:InterwikiSorting|InterwikiSorting extension]], which allowed for the [[m:Special:MyLanguage/Interwiki sorting order|sorting of interwiki links]], has been undeployed from Wikipedia. As a result, editors who had enabled interwiki link sorting in non-compact mode (full list format) will now see links reordered. The links moving forward will be listed in the alphabetical order of language code. [https://phabricator.wikimedia.org/T253764] * Later this week, people who are editing a page-section using the mobile visual editor, will notice a new "Edit full page" button. When tapped, you will be able to edit the entire article. This helps when the change you want to make is outside the section you initially opened. [https://phabricator.wikimedia.org/T387175][https://phabricator.wikimedia.org/T409112] * [[mw:Special:MyLanguage/Readers/Reader Experience|The Reader Experience team]] is inviting editors to assess whether dark mode should still be considered "beta" on their wiki, based on their experience of how well it functions on desktop and mobile. If the feature is deemed mature, editors can update the interface messages in <code dir=ltr>MediaWiki:skin-theme-description</code> and <code dir=ltr>MediaWiki:Vector-night-mode-beta-tag</code> to indicate that dark mode is ready and no longer considered beta. * The improved [[mw:Wikimedia_Apps/Team/iOS/Activity_Tab|Activity tab]] which displays user-insights is now available to all users of the Wikipedia iOS app (version 7.9.0 and later). Following earlier A/B testing that showed higher account creation among users with access to the feature, it has been rolled out to 100% of users along with some updates. The Activity tab now shows your edited articles in the timeline, offers editing impact insights like contribution counts and article view trends, and customization options to improve in-app experience for users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, a bug that prevented [[mw:Special:MyLanguage/Extension:DiscussionTools|DiscussionTools]] from working on mobile has now been fixed, restoring full functionality. [https://phabricator.wikimedia.org/T415303] '''Updates for technical contributors''' * The [[m:Special:GlobalWatchlist|Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] that makes this possible continues to improve. The latest upgrade is the inclusion of a [[mw:Extension:GlobalWatchlist#hook|new hook]], <code dir=ltr>ext.globalwatchlist.rebuild</code>, which fires after each watchlist rebuild. This allows you to run gadgets and user scripts for the Special page. [https://phabricator.wikimedia.org/T275159] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.17|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/09|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W09"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 février 2026 à 20:03 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30119102 --> == Actualités techniques n° 2026-10 == <section begin="technews-2026-W10"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/10|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments|mode Anniversaire]] Wikipedia 25 est maintenant disponible sur Wikipédia en français, anglais, betawi, breton, chinois, espagnol, gorontalo, indonésien, italien, luxembourgeois, madurais, néerlandais, sicilien, tchèque, thaï et vietnamien ! Cette campagne à temps limitée célèbre 25 ans de Wikipédia avec une mascotte : « Baby Globe », disponible sous la forme d'un réglage. Lorsque ce réglage est activé, Baby Globe est montrée sur [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments/article configuration|environ 2 500 articles]], attendant d'être découverte par des lecteurs. Chaque communauté peut choisir d'activer le mode Anniversaire par consensus et en demandant à un administrateur de le rendre disponible et de le personaliser via une [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments#Community Configuration Demo|configuration]] sur le wiki local. '''Actualités pour la contribution''' * Le [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-référencement]], une nouvelle fonctionalité pour réutiliser des références avec des détails différents est maintenant disponible sur Wikipédia en suédois, polonais et [[:phab:T418209|quelques autres]]. Vous pouvez [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#test|essayer la fonctionalité]] sur ces projets ou sur testwiki et [https://en.wikipedia.beta.wmcloud.org/wiki/Sub-referencing betawiki]. Les retours des premiers essais sur Wikipédia en allemand ont été [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing/Learnings|publiés dans un rapport]]. Contactez l'équipe de Wikimédia Allemagne si vous êtes [[:m:Talk:WMDE Technical Wishes/Sub-referencing#Pilot wikis|intéressés pour devenir un wiki pilote]]. * La [[mw:Special:MyLanguage/Help:Edit check#Paste check|vérification du collage clavier]] sera disponible sur tous les Wikipédias cette semaine. Cette fonctionalité avertit les nouveaux contributeurs qui collent du texte qu'ils n'ont probablement pas écrit de vérifier si laisser celui-ci risque de causer une violation du droit d'auteur. La vérification du collage clavier [[mw:Special:MyLanguage/Edit check/Tags|marque]] toutes les modifications où l'avertissement a été montré pour permettre leur vérification. Les administrateurs locaux peuvent configurer les différents aspects de cette fonctionalité à travers [[{{#special:EditChecks}}]]. Des [[mw:Special:MyLanguage/Edit check/Paste Check#A/B Experiment|études]] sur 22 wikis ont montré que cette vérification permet une réduction de 18% des annulations comparé au groupe de contrôle. Les traducteurs peuvent [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-visualeditor-ve-mw-editcheck&filter=&optional=1&action=translate aider à traduire] cette fonctionalité. * <span lang="en" dir="ltr" class="mw-content-ltr">The [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience team]] will be standardizing the user menu in the top right for all mobile users so that it is closer to the desktop experience. Currently this user menu is only visible to users with Advanced Mobile Controls (AMC) turned on. The only change is that a couple buttons previously in the left-side menu will move to the top right for users who do not have AMC turned on. This change is expected to go out March 9 and seeks to improve the user interface.</span> [https://phabricator.wikimedia.org/T413912] * À partir de la semaine du 2 mars, les emails envoyés lorsqu'une adresse email a été ajoutée, supprimée ou changée pour un compte changera pour adopter un formattage HTML beaucoup plus agréable et plus clair que le texte brut précédent. [https://phabricator.wikimedia.org/T410807] * Les notifications sont actuellement limitées à 2 000 entrées historiques par utilisateur et remontent à 2013 lorsque la fonctionnalité a été publiée. Le système va être modifié pour ne stocker que les notifications des 5 dernières années, mais jusqu'à 10 000 d'entre elles. Cela contribuera à la santé à long terme des infrastructures et à empêcher que les notifications plus récentes disparaissent trop tôt. [https://phabricator.wikimedia.org/T383948] * <span lang="en" dir="ltr" class="mw-content-ltr">The [[m:Special:GlobalWatchlist|Global Watchlist]] which lets you view your watchlists from multiple wikis on a single page continues to see improvements. The latest update improves label usage experience. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] now allows activating the [[mw:Special:MyLanguage/Manual:Language#Fallback languages|language fallback system]] for Wikidata items without labels in the viewed language, and showing those labels in the user’s preferred Wikidata language if no <code dir=ltr>uselang=</code> URL parameter is provided.</span> [https://phabricator.wikimedia.org/T373686][https://phabricator.wikimedia.org/T416111] * L'équipe Wikipédia Android a commencé un test beta de la [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|recherche hybride]] sur Wikipédia en grec. Cette recherche hybride supporte les requêtes sémantique et par mot clés, permettant aux utilisateurs de trouver ce qu'ils cherchent plus facilement. * Pour des raisons de sécurité, les membres de certains groupes sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir la double authentification]] (A2F) d'activée. Actuellement, l'A2F n'est nécessaire que pour utiliser les droits du groupe, et non pour en faire partie. Vu que ce système admet certaines failles, il sera [[phab:T418580|changé graduellement en mars]]. Les membres de ces groupes ne pourront plus désactiver la dernière méthose d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Il sera toujours possible de rajouter d'autres méthodes d'authentification et d'en enlever, tant qu'une est toujours activée. Dans la seconde moitié de mars, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique aux administrateurs CentralNotice, aux vérificateurs d'utilisateurs, aux administrateurs d'interface, aux masqueurs, aux staff de Wikidata et Wikifonctions ainsi qu'aux bureaux IT et Confiance et sécurité de la WMF. Rien ne changera pour les autres utilisateurs. Voir la tâche liée pour le calendrier de déploiement. [https://phabricator.wikimedia.org/T418580] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, le problème empêchant les utilisateurs de créer une instance dans [https://www.wikibase.cloud/ Wikibase.cloud] a maintenant été résolu. [https://phabricator.wikimedia.org/T416807] '''Actualités pour la contribution technique''' * <span lang="en" dir="ltr" class="mw-content-ltr">To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], over the next month the Wikimedia Foundation will implement global API rate limits across our APIs. In early March, stricter limits will be applied to unidentified requests from outside Toolforge/WMCS and API requests that are made from web browsers. In April, higher limits will be applied to identified traffic. These limits are intentionally set as high as possible to minimise impact on the community. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]].</span> * <span lang="en" dir="ltr" class="mw-content-ltr">The Wikidata Query Service Linked Data Fragment (LDF) endpoint will be decommissioned in February. This endpoint served limited traffic, which was successfully migrated to other data access methods that were better suited to support existing use cases. The hardware used to support the LDF endpoint will be reallocated to support the ongoing backend migration efforts.</span> [https://phabricator.wikimedia.org/T415696] * Le nouvel analyseur syntaxique Parsoid [[mw:Special:MyLanguage/Parsoid/Parser Unification/Updates|continue d'être déployés sur plus de wikis]], améliorant la pérennité de la platforme et rendant plus facile l'ajout de nouvelles fonctionalités de lecture et de modification. Parsoid est maintenant l'analyseur par défaut sur 488 wikis de la WMF (268 Wikipédias), couvrant plus de 10% de toutes les lectures de pages Wikipédia. * Le processus et les critères pour [[Special:MyLanguage/Wikimedia Enterprise#Access|demander un accès exceptionnel]] au flux à fort volume de l'API ''Wikimédia Entreprise'' (sans coût pour des utilisations en rapport à notre mission) [[m:Talk:Wikimedia Enterprise#Exceptional access criteria|ont maintenant été publiés]]. Notre but est de donner une documentation plus claire et plus complète aux utilisateurs. * [https://techblog.wikimedia.org/ Le blog Tech], dédié à la communité technique de Wikimédia [https://techblog.wikimedia.org/2026/02/24/a-tech-blog-diff/ va migrer] vers [[diffblog:|Diff]], le blog pour les nouvelles et événements de la communauté. La migration devrait être terminée en Avril 2026, après quoi les nouveaux posts seront acceptés pour être publiés. Les lecteurs pourront lire les posts - anciens ou nouveaux - sur https://diff.wikimedia.org/. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.18|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/10|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W10"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 mars 2026 à 18:51 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30137798 --> == <span lang="en" dir="ltr">Tech News: 2026-11</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W11"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/11|Translations]] are available. '''Weekly highlight''' * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. * Last week, all wikis had 2 hours of read-only time, and extended unavailability for user-scripts and gadgets. This was due to a security incident which has since been resolved. Work is ongoing to prevent re-occurrences. For current information please see the [[m:Steward's noticeboard#Statement on Meta about today's user script security incident|post on the Stewards' noticeboard]] ([[m:Special:MyLanguage/Wikimedia Foundation/Product and Technology/Product Safety and Integrity/March 2026 User Script Incident|translations]]). '''Updates for editors''' * Users facing multiple blocks on mobile will now see the reasons for each block separately, instead of a generic message. This helps them understand why they are blocked and what steps they can take to resolve the issue. For example, users affected for using common VPNs (such as [[Special:MyLanguage/Apple iCloud Private Relay|iCloud Private Relay]]) will receive clearer guidance on what they need to do to start editing again. [https://phabricator.wikimedia.org/T357118] * Later this week, [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Suggestion Mode]] will become available as a beta feature within the visual editor at all Wikipedias. This feature proactively suggests various types of actions that people can consider taking to improve Wikipedia articles, and learn about related guidelines. The feature is locally configurable, and can also be locally expanded with custom Suggestions. Current settings can be seen at [[Special:EditChecks]] and there are [[mw:Special:MyLanguage/Help:Suggestion mode#For administrators %E2%80%93 local customization|instructions for how administrators can customize]] the links to point to local guidelines. The feature is connected to [[mw:Special:MyLanguage/Help:Edit check|Edit check]] which suggests improvements while someone is writing new content. In the future, the Editing team plans to evaluate the feature's impact with newcomers through a controlled experiment. [https://phabricator.wikimedia.org/T404600] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:23}} community-submitted {{PLURAL:23|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the issue where the cursor became misaligned during the use of CodeMirror’s syntax highlighting, which makes wikitext and code easier to read, has now been fixed. This problem specifically affected users who defined a font rule in a custom stylesheet while creating a new topic with DiscussionTools. [https://phabricator.wikimedia.org/T418793] '''Updates for technical contributors''' * API rate limiting update: To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], global API rate limits will be applied this week to requests without a compliant User-Agent that originate from outside Toolforge/WMCS and to unauthenticated requests made from web browsers. Higher limits will be applied to identified traffic in April. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]]. * The new GraphQL API has been released. The API was developed as a flexible alternative to select features of the Wikidata Query Service (WDQS), to improve developer experience and foster adaptability, and efficient data access. Try it out and [[d:Wikidata:Wikibase GraphQL#Feedback and development|give feedback]]. You can also [https://greatquestion.co/wikimediadeutschland/GraphQLAPI/apply sign up for usability tests]. * The [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group|PTAC Unsupported Tools Working Group]] continued improvements to [[commons:Special:MyLanguage/Commons:Video2commons#|Video2Commons]] in February, with fixes addressing authentication errors, large-file handling, task queue visibility, and clearer upload behavior. Work is still ongoing in some areas, including changes related to deprecated server-side uploads. Read [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group#February 2026|this update]] to learn more. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.19|MediaWiki]] '''In depth''' * The Article Guidance team invites experienced Wikipedia editors from selected [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators#Collaborators|pilot wikis]] and interested contributors from other Wikipedias to fill out this questionnaire which is available in [https://docs.google.com/forms/d/e/1FAIpQLSfmLeVWnxmsCbPoI_UF2jyRcn73WRGWCVPHzerXb4Cz97X_Ag/viewform English], [https://docs.google.com/forms/d/e/1FAIpQLSd6rzr4XXQw8r4024fE3geTPFe13M_6w7Mitj-YJi0sOlWTAw/viewform?usp=header Arabic], [https://docs.google.com/forms/d/e/1FAIpQLSdok3-RfB18lcugYTUMGkpwmqG_8p760Wv4dCXitOXOszjUDw/viewform?usp=header Bengali], [https://docs.google.com/forms/d/e/1FAIpQLSfjTfYp4jEo0akA4B1e-Nfg3QZPCudUjhJzHzzDi6AHyAaMGA/viewform?usp=header Japanese], [https://docs.google.com/forms/d/e/1FAIpQLScteVoI29Aue4xc72dekk-6RYtvmMgQxzMI900UOawrFrSTWg/viewform?usp=header Portuguese], [https://docs.google.com/forms/d/e/1FAIpQLSetdxnYwL3ub2vqA7awCg5hJZPMIYcDPaiTe12rY9h0GYnVlw/viewform?usp=header Persian], and [https://docs.google.com/forms/d/e/1FAIpQLScNvfJF-Ot-4pzA4qAN771_0QDJ4Li19YcUsaTgSKW8Nc7U_Q/viewform?usp=header Turkish]. Your answers will help the team customize guidance for less experienced editors and help them learn community policies and practices while creating an article. Learn more [[mw:Special:MyLanguage/Article guidance|on the project page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/11|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W11"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 9 mars 2026 à 19:52 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30213008 --> == <span lang="en" dir="ltr">Tech News: 2026-12</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W12"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/12|Translations]] are available. '''Updates for editors''' * The [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature, also known as [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], has been used for wikitext syntax highlighting since November 2024. It will be promoted out of beta by May 2026 in order to bring improvements and new [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Features|features]] to all editors who use the standard syntax highlighter. If you have any questions or concerns about promoting the feature out of beta, [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|please share]]. [https://phabricator.wikimedia.org/T259059] * Some changes to local user groups are performed by stewards on Meta-Wiki and logged there only. Now, interwiki rights changes will be logged both on Meta-Wiki and the wiki of the target user to make it easier to access a full record of user's rights changes on a local wiki. Past log entries for such changes will be backfilled in the coming weeks. [https://phabricator.wikimedia.org/T6055] * On wikis using [[m:Special:MyLanguage/Flagged Revisions|Flagged Revisions]], the number of pending changes shown on [[{{#Special:PendingChanges}}]] previously counted pages which were no longer pending review, because they have been removed from the system without being reviewed, e.g. due to being deleted, moved to a different namespace, or due to wiki configuration changes. The count will be correct now. On some wikis the number shown will be much smaller than before. There should be no change to the list of pages itself. [https://phabricator.wikimedia.org/T413016] * Wikifunctions composition language has been rewritten, resulting in a new version of the language. This change aims to increase service stability by reducing the orchestrator's memory consumption. This rewrite also enables substantial latency reduction, code simplification, and better abstractions, which will open the door to later feature additions. Read more about [[f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-11|the changes]]. * Users can now sort search results alphabetically by page title. The update gives an additional option to finding pages more easily and quickly. Previously, results could be sorted by Edit date, Creation date, or Relevance. To use the new option, open 'Advanced Search' on the search results page and select 'Alphabetically' under 'Sorting Order'. [https://phabricator.wikimedia.org/T403775] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:28}} community-submitted {{PLURAL:28|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented UploadWizard on Wikimedia Commons from importing files from Flickr has now been fixed. [https://phabricator.wikimedia.org/T419263] '''Updates for technical contributors''' * A new special page, [[{{#special:LintTemplateErrors}}]], has been created to list transcluded pages that are flagged as containing lint errors to help users discover them easily. The list is sorted by the number of transclusions with errors. For example: [[{{#special:LintTemplateErrors}}/night-mode-unaware-background-color]]. [https://phabricator.wikimedia.org/T170874] * Users of the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature have been using [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] for syntax highlighting when editing JavaScript, CSS, JSON, Vue and Lua content pages, for some time now. Along with promoting CodeMirror 6 out of beta, the plan is to replace CodeEditor as the standard editor for these content models by May 2026. [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|Feedback or concerns are welcome]]. [https://phabricator.wikimedia.org/T419332] * The [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] JavaScript modules will soon be upgraded to CodeMirror 6. Leading up to the upgrade, loading the <code dir=ltr>ext.CodeMirror</code> or <code dir=ltr>ext.CodeMirror.lib</code> modules from gadgets and user scripts was deprecated in July 2025. The use of the <code dir=ltr>ext.CodeMirror.switch</code> hook was also deprecated in March 2025. Contributors can now make their scripts or gadgets compatible with CodeMirror 6. See the [[mw:Special:MyLanguage/Extension:CodeMirror#Gadgets and user scripts|migration guide]] for more information. [https://phabricator.wikimedia.org/T373720] * The MediaWiki Interfaces team is expanding coverage of REST API module definitions to include [[mw:Special:MyLanguage/API:REST API/Extensions|extension APIs]]. REST API modules are groups of related endpoints that can be independently managed and versioned. Modules now exist for [https://phabricator.wikimedia.org/T414470 GrowthExperiments] and [https://phabricator.wikimedia.org/T419053 Wikifunctions] APIs. As we migrate extension APIs to this structure, documentation will move out of the main MediaWiki OpenAPI spec and REST Sandbox view, and will instead be accessible via module-specific options in the dropdown on the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox] (i.e., [[{{#Special:RestSandbox}}]], available on all wiki projects). * The [[mw:Special:MyLanguage/Extension:Scribunto|Scribunto]] extension provides different pieces of information about the wiki where the module is being used via the [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual|mw.site]] library. Starting last week, the library also provides a [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#mw.site.wikiId|way]] of accessing the [[mw:Special:MyLanguage/Manual:Wiki ID|wiki ID]] that can be used to facilitate cross-wiki module maintenance. [https://phabricator.wikimedia.org/T146616] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.20|MediaWiki]] '''In depth''' * The [[m:Special:MyLanguage/Coolest Tool Award|2026 Coolest Tool Award]] celebrating outstanding community tools, is now open for nominations! Nominate your favorite tool using the [https://wikimediafoundation.limesurvey.net/435684?lang=en nomination survey] form by 23 March 2026. For more information on privacy and data handling, please see the [[foundation:Special:MyLanguage/Legal:Coolest_Tool_Award_2026_Survey_Privacy_Statement|survey privacy statement]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/12|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W12"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 mars 2026 à 20:35 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30260505 --> == <span lang="en" dir="ltr">Upcoming deployment of CampaignEvents extension to Wikibooks</span> == <div lang="en" dir="ltr"> <section begin="message"/> Hello everyone, We are writing to inform you that the [[mw:Help:Extension:CampaignEvents|CampaignEvents extension]] will be deployed to all Wikibooks projects during the week of '''23 March 2026'''. This follows last year’s broader rollout across Wikimedia projects. We realized that Wikibooks was not included at the time, and we’re now addressing that to ensure consistency across all communities. The CampaignEvents extension provides tools to support event and campaign organization on-wiki, including features like on-wiki event registration and collaboration lists(global event list). We welcome any questions, feedback, or concerns you may have. We are also happy to support anyone interested in trying out the tools. ''Apologies if this message is not in your preferred language. If you’re able to help translate it for your community, please feel free to do so.'' <section end="message"/> </div> <bdi lang="en" dir="ltr">[[User:Udehb-WMF|Udehb-WMF]] ([[User talk:Udehb-WMF|discussion]]) 19 mars 2026 à 19:22 (CET)</bdi> <!-- Message envoyé par User:Udehb-WMF@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=User:Udehb-WMF/sandbox/MM_target&oldid=30284073 --> == <span lang="en" dir="ltr">Tech News: 2026-13</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W13"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/13|Translations]] are available. '''Weekly highlight''' * Wikimedia site users can now log in without a password using passkeys. This is a secure method supported by fingerprint, facial recognition, or PIN. With this change, all users who opt for passwordless login will find it easier, faster, and more secure to log in to their accounts using any device. The new passkey login option currently appears as an autofill suggestion in the username field. An additional [[phab:T417120|"Log in with passkey" button]] will soon be available for users who have already registered a passkey. This update will improve security and user experience. The [[c:File:Passwordless_login_screencast.webm|screen recording]] demonstrates the passwordless login process step by step. * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. '''Updates for editors''' * Wikimedia site users can now export their notifications older than 5 years using a [[toolforge:echo-chamber|new Toolforge tool]]. This will ensure that users retain their important notifications and avoid them being lost based on the planned change to delete notifications older than 5 years, as previously announced. [https://phabricator.wikimedia.org/T383948] * Wikipedia editors in Indonesian, Thai, Turkish, and Simple English now have access to Special:PersonalDashboard. This is an [[mw:Special:MyLanguage/Moderator Tools/Dashboard|early version of an experience]] that introduces newer editors to patrolling workflows, making it easier for them to move from making edits to participating in more advanced moderation work on their project. [https://phabricator.wikimedia.org/T402647] * The [[Special:Block]] now has two minor interface changes. Administrators can now easily perform indefinite blocks through a dedicated radio button in the expiry section. Also, choosing an indefinite expiry provides a different set of common reasons to select from, which can be changed at: [[MediaWiki:Ipbreason-indef-dropdown]]. [https://phabricator.wikimedia.org/T401823] * Mobile editors [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#Logged-out|at several wikis]] can now see an improved logged-out edit warning, thanks to the recent updates from the Growth team. These changes released last week are part of ongoing efforts and tests to enhance [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|account creation experience on mobile]] and then increase participation. [https://phabricator.wikimedia.org/T408484] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:36}} community-submitted {{PLURAL:36|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented mobile web users from seeing the block information when affected by multiple blocks has been fixed. They can now see messages of all the blocks currently affecting them when they access Wikipedia. '''Updates for technical contributors''' * Images built using Toolforge will soon get the upgraded buildpacks version, bringing support for newer language versions and other upstream improvements and fixes. If you use Toolforge Build Service, review the recent [https://lists.wikimedia.org/hyperkitty/list/cloud-announce@lists.wikimedia.org/thread/EMYTA32EV2V5SQ2JIEOD2CL66YFIZEKV/ cloud-announce email] and update your build configuration as necessary to ensure your tools are compatible. [https://wikitech.wikimedia.org/w/index.php?title=Help:Toolforge/Building_container_images&oldid=2392097#Buildpack_environment_upgrade_process][https://phabricator.wikimedia.org/T380127] * The [https://api.wikimedia.org/wiki/Main_Page API Portal] documentation wiki will shut down in June 2026. API keys created on the API Portal will continue to work normally. api.wikimedia.org endpoints will be deprecated gradually starting in July 2026. Documentation on the API Portal is moving to [[mw:Wikimedia APIs|mediawiki.org]]. Learn more on the [[wikitech:API Portal/Deprecation|project page]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.21|MediaWiki]] '''In depth''' * [[m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]] is considering improvements to [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names|automatically generated reference names in VisualEditor]]. Please check out the [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names#Proposed solutions|proposed solutions]] and participate in the [[m:Talk:WMDE Technical Wishes/References/VisualEditor automatic reference names#Request for comment|request for comment]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/13|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W13"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 mars 2026 à 17:51 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30268305 --> == Actualités techniques n° 2026-14 == <section begin="technews-2026-W14"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/14|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le version Beta de [[abstract:|Abstract Wikipedia]], un nouveau projet Wikimédia indépendant du langage, a été lancée la semaine dernière. Ce projet permet aux communautés de construire des articles Wikipédia dans leur langue natale, qui peuvent directement être lus par les autres utilisateurs et utilisatrices dans leur propre langage. Le wiki fonctionne grâce à des instructions de Wikifunctions et au contenu structuré issu de Wikidata. [[:f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-26|En savoir plus]]. '''Actualités pour la contribution''' * L'équipe Croissance mène un test A/B afin d'évaluer l'effet d'un message plus clair et plus convivial encourageant à la création de comptes sur les wikis. Actuellement, lorsqu'un utilisateur mobile non connecté lance la modification, un message d'avertissement s'affiche, pouvant paraître abrupt et décourageant. Il présente également la modification par compte temporaire comme option par défaut, au lieu d'inciter à la création d'un compte. Le test est mené sur dix Wikipédia, dont les versions en arabe, français, espagnol et allemand. [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#2. Improve logged-out warning message (T415160)|En savoir plus]]. * L'équipe des applications Wikimédia sollicite vos commentaires sur [[mw:Special:MyLanguage/Wikimedia Apps/Team/Future of Editing on the Mobile Apps|comment devrait fonctionner l'édition dans les applications mobiles Wikipédia]]. La discussion porte sur l'amélioration de l'accès aux outils d'édition lorsque les utilisateurs appuient sur « Modifier ». Cette initiative s'inscrit dans un effort plus large visant à offrir aux lecteurs intéressés par la contribution une expérience utilisateur plus intuitive. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:45|la tâche soumise|les {{formatnum:45}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:45||s}} la semaine dernière]]. Par exemple, un problème avec la récupération de citations à partir du site d'archive de journaux [https://www.newspapers.com Newspapers.com], qui ne fonctionnait plus en raison d'un blocage des requêtes [[mw:Special:MyLanguage/Citoid|Citoid]], a maintenant été résolu. [https://phabricator.wikimedia.org/T419903] '''Actualités pour la contribution technique''' * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.22|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/14|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W14"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 30 mars 2026 à 21:25 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30329462 --> == Action Required: Update templates/modules for electoral maps (Migrating from P1846 to P14226) == Hello everyone, This is a notice regarding an ongoing data migration on Wikidata that may affect your election-related templates and Lua modules (such as <code>Module:Itemgroup/list</code>). '''The Change:'''<br /> Currently, many templates pull electoral maps from Wikidata using the property [[:d:Property:P1846|P1846]], combined with the qualifier [[:d:Property:P180|P180]]: [[:d:Q19571328|Q19571328]]. We are migrating this data (across roughly 4,000 items) to a newly created, dedicated property: '''[[:d:Property:P14226|P14226]]'''. '''What You Need To Do:'''<br /> To ensure your templates and infoboxes do not break or lose their maps, please update your local code to fetch data from [[:d:Property:P14226|P14226]] instead of the old [[:d:Property:P1846|P1846]] + [[:d:Property:P180|P180]] structure. A [[m:Wikidata/Property Migration: P1846 to P14226/List|list of pages]] was generated using Wikimedia Global Search. '''Deadline:'''<br /> We are temporarily retaining the old data on [[:d:Property:P1846|P1846]] to allow for a smooth transition. However, to complete the data cleanup on Wikidata, the old [[:d:Property:P1846|P1846]] statements will be removed after '''May 1, 2026'''. Please update your modules and templates before this date to prevent any disruption to your wiki's election articles. Let us know if you have any questions or need assistance with the query logic. Thank you for your help! [[User:ZI Jony|ZI Jony]] using [[Utilisateur:MediaWiki message delivery|MediaWiki message delivery]] ([[Discussion utilisateur:MediaWiki message delivery|discussion]]) 3 avril 2026 à 19:11 (CEST) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29941252 --> == Actualités techniques n° 2026-15 == <section begin="technews-2026-W15"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/15|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * L’[[mw:Special:MyLanguage/Help:Extension:CampaignEvents|extension CampaignEvents]] comprend désormais une nouvelle fonctionnalité de définition d’objectifs de groupe, permettant aux organisateurs de définir et de suivre les objectifs de l’événement, tels que le nombre d’articles créés et de contributeurs participants en temps réel. De même, les participants peuvent travailler vers des cibles communes et voir leur impact collectif au fur et à mesure que l’événement se déroule. Cette fonctionnalité est désormais disponible sur tous les wikis Wikimedia. Pour en savoir plus, consultez [[mw:Special:MyLanguage/Help:Extension:CampaignEvents/Registration/Collaborative contributions#Goal setting|la documentation]]. * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] La nouvelle fonctionnalité d'[[mw:Special:MyLanguage/Help:Watchlist labels|étiquettes de liste de suivi]] (annoncée dans les [[m:Special:MyLanguage/Tech/News/2026/07|Actualités techniques 2026-07 ]]) est désormais disponible via l'ÉditeurVisuel, l'éditeur de code et l'«étoile de suivi»(ou le lien de suivi, pour les habillages qui n'ont pas d'icône d'étoile). Auparavant, il n'était possible d'attribuer des étiquettes que via [[Special:EditWatchlist|Modifier la liste de suivi]]. Dans ces trois emplacements, il s'agit d'un nouveau champ situé après le champ d'expiration. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. Par exemple, le problème où les pages de discussion sur mobile avec Parsoid sont inutilisables après les en-têtes de section vides, a maintenant été résolu. [https://phabricator.wikimedia.org/T419171] '''Actualités pour la contribution technique''' * La [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|fonctionnalité de sous-référencement]], qui permet aux contributeurs d'ajouter des détails à une référence existante sans la dupliquer, sera progressivement déployée sur [[phab:T414094|davantage de wikis]] plus tard cette année. Les wikis utilisant le gadget [[mw:Special:MyLanguage/Reference Tooltips|Reference Tooltips]] sont encouragés à mettre à jour leur version (généralement sur [[m:MediaWiki:Gadget-ReferenceTooltips.js|MediaWiki:Gadget-ReferenceTooltips.js]] comme indiqué [https://en.wikipedia.org/w/index.php?diff=1344408362 ici]) pour assurer la compatibilité. D'autres gadgets liés aux références pourraient également être affectés. [https://phabricator.wikimedia.org/T416304] * Toutes les éditions de Wikinews seront fermées et passeront en mode lecture seule le 4 mai 2026. Le contenu restera accessible, mais aucune nouvelle modification ni aucun nouvel article ne pourra être ajouté. Cette fermeture a été approuvée par le Conseil d'administration de la Fondation Wikimedia à la suite de discussions prolongées. [[m:Wikimedia Foundation Board noticeboard#Board of Trustees Approves Closure of Wikinews|En savoir plus]]. * L'[[:mw:Special:MyLanguage/API:Action API|API d'action]] a proposé plusieurs formats pour les résultats demandés. L'un d'entre eux, <bdi lang="zxx" dir="ltr"><code><nowiki>format=php</nowiki></code></bdi>, sera bientôt supprimé. Veuillez vous assurer que vos scripts ou robots utilisent le [[mw:Special:MyLanguage/API:Data formats#Output|format JSON]]. Cette suppression devrait affecter très peu de scripts et de robots. [https://phabricator.wikimedia.org/T118538] * La page [[Special:NamespaceInfo|Special:NamespaceInfo]] inclut désormais les alias d'espace de noms. Par exemple «WP» pour l'espace de noms ''Projet'' (''Wikipédia'') sur la Wikipédia en allemand. [https://phabricator.wikimedia.org/T381455] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.23|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/15|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W15"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 6 avril 2026 à 18:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30362761 --> == <span lang="en" dir="ltr">Tech News: 2026-16</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W16"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/16|Translations]] are available. '''Weekly highlight''' * Experienced editors are invited to [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Main_Page test] the [[mw:Special:MyLanguage/Article guidance|Article guidance]] feature, designed to help less-experienced editors create well-structured, policy-compliant Wikipedia articles. Testing instructions are [[mw:Special:MyLanguage/Article guidance/Test feature guide|available]]. Also, after reviewing [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Category:Pages_using_article_guidance the outlines], please provide feedback on the [[mw:Talk:Article guidance|project talk page]]. Based on your input, the feature will be refined and transferred to the pilot Wikipedias to translate and adapt. Check out [[c:File:Article Guidance workflow demo - April 2026.webm|the video]] explaining the feature. '''Updates for editors''' * On most wikis, all autoconfirmed users can now use [[Special:ChangeContentModel|Special:ChangeContentModel]] page to [[mw:Special:MyLanguage/Help:ChangeContentModel|create new pages with custom content models]], such as mass message lists, making custom page formats more accessible. Check [[Special:ListGroupRights|Special:ListGroupRights]] for the status of your wiki. [https://phabricator.wikimedia.org/T248294] * The Growth team has launched an [[mw:Special:MyLanguage/Contributors/Account_Creation_Experiments|account creation experiment]] to evaluate whether adding an account creation button to the mobile web header increases new account registrations and encourages more mobile users to contribute to the wikis. The experiment is currently live on Hindi, Indonesian, Bengali, Thai, and Hebrew Wikipedia, and targets 10% of logged-out mobile web users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:30}} community-submitted {{PLURAL:30|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, an issue where VisualEditor could get stuck loading on Windows devices with animations turned off, has now been fixed. [https://phabricator.wikimedia.org/T382856] '''Updates for technical contributors''' * Starting later this week, {{int:group-abusefilter}} who have the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature enabled will have [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] as the editor at [[Special:AbuseFilter|Special:AbuseFilter]]. This is part of the broader effort to make the user experience more consistent across all editors. [https://phabricator.wikimedia.org/T399673][https://phabricator.wikimedia.org/T419332] * Tools and bots that access the [[mw:Special:MyLanguage/Notifications/API|Notifications API]] (<bdi lang="zxx" dir="ltr"><code><nowiki>action=query&meta=notifications</nowiki></code></bdi>) will need to update their OAuth or BotPassword grants to also include access to private notifications. [https://phabricator.wikimedia.org/T421991] * Due to a library upgrade, listings on category pages may be displayed out of order starting on Monday, 20th April. A migration script will be run to correct this, and will take hours to days depending on the size of the wiki (up to a week for English Wikipedia). [https://phabricator.wikimedia.org/T422544] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.24|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/16|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W16"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 13 avril 2026 à 17:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30380527 --> == Actualités techniques n° 2026-17 == <section begin="technews-2026-W17"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/17|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Après deux ans de développement, la version [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]], également connue sous le nom de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], sortira de sa phase bêta le mardi 21 avril. Elle offrira une meilleure lisibilité du code et du wikitext, une réduction des fautes de frappe et d'autres [[mw:Special:MyLanguage/Help:Extension:CodeMirror|avantages]] à tous les utilisateurs du surligneur de syntaxe standard. Un grand merci au bénévole [https://phabricator.wikimedia.org/p/Bhsd/ Bhsd] qui a développé de nombreuses nouvelles fonctionnalités, notamment [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Code folding|le repliement de code]], [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Autocompletion|la saisie semi-automatique]] et [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Linting|l'analyse statique du code]]. [https://phabricator.wikimedia.org/T259059] * Une mise à jour majeure de l'application Wikipédia pour iOS est en cours de déploiement, en restructurant l'interface pour s'harmoniser avec le tout nouveau design visuel "Liquid Glass" d'Apple. [https://apps.apple.com/us/app/wikipedia/id324715238 Télécharger la dernière version] et découvrez les nouveautés. '''Actualités pour la contribution''' * [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|Les listes de lecture]] est une fonctionnalité qui permet aux lecteurs d'enregistrer des articles dans une liste pour les lire ultérieurement. Cette fonctionnalité est actuellement en version bêta sur les Wikipédias en arabe, français, indonésien, vietnamien et chinois, et activée par défaut pour tous les nouveaux comptes sur toutes les Wikipédias. * Une expérimentation visant à étendre [[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews|les aperçus de page au web mobile]] sera lancée la semaine du 20 avril sur les versions arabe, anglaise, française, italienne, polonaise et vietnamienne de Wikipédia. Les aperçus de page sont des fenêtres contextuelles affichant une miniature, un premier paragraphe et un lien bleu permettant d'ouvrir l'article complet, facilitant ainsi la découverte de contenu. Cette fonctionnalité est déjà disponible sur ordinateur et dans les applications. [[m:Special:MyLanguage/List of experiments in Product and Technology#Template|En savoir plus sur cette expérimentation et d'autres]]. * Sur plusieurs wikis, les contributeurs connectés qui n'ont pas [[mw:Special:MyLanguage/Help:Email confirmation|confirmé leur adresse électronique]] peuvent désormais voir une bannière les invitant à le faire. La confirmation de l'adresse électronique permet à un utilisateur de récupérer l'accès à son compte en cas de perte. [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security#Encouraging users to confirm their email addresses|En savoir plus]]. [https://phabricator.wikimedia.org/T421366] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:15|la tâche soumise|les {{formatnum:15}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:15||s}} la semaine dernière]]. Par exemple, un problème qui entraînait des ralentissements lors de la modification de très grandes pages wiki dans l'éditeur wikitext de 2017, des problèmes de chargement, de prévisualisation et de défilement, ainsi que des problèmes de performance lors de la sélection, de la découpe ou du collage de contenu, a maintenant été résolu. [https://phabricator.wikimedia.org/T184857] '''Actualités pour la contribution technique''' * Dans le cadre de la promotion de [[mw:Special:MyLanguage/Help:Extension:CodeMirror|CodeMirror]] à partir d'une fonctionnalité bêta, tous les utilisateurs se serviront de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] au lieu de [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] pour la coloration syntaxique lors de l'édition de pages de contenu JavaScript, CSS, JSON, Vue et Lua. [https://phabricator.wikimedia.org/T419332] * <span class="mw-translate-fuzzy">Le service <code>mirrors.wikimedia.org</code> pour les utilisateurs de Debian et Ubuntu sera définitivement arrêté le 15 mai. Le matériel du serveur sera remplacé par des solutions plus performantes. Certains utilisateurs devront peut-être migrer vers un autre serveur qui ne devra prendre qu'une minute. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/LJYRIS4WB66HIRCAO4GIDTXCMDVZRBMA/ Vous pouvez en savoir plus].</span> [https://phabricator.wikimedia.org/T416707] * Les tables <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi> seront supprimées de [[wikitech:Help:Wiki Replicas|wikireplicas]]. Si vos outils ou requêtes accèdent directement à <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> ou <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi>, veuillez les mettre à jour pour utiliser les tables <bdi lang="zxx" dir="ltr"><code><nowiki>file</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>filerevision</nowiki></code></bdi> avant le 28 mai. [https://phabricator.wikimedia.org/T28741] * Suite à la récente mise en place de limites de débit globales pour les API non identifiées, la Fondation Wikimedia poursuit ses efforts pour garantir [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|une utilisation équitable de l'infrastructure]] en appliquant des limites globales au trafic des API identifiées à partir de la dernière semaine d'avril. Ces limites sont volontairement fixées au niveau le plus élevé possible afin de minimiser l'impact sur la communauté. Les bots exécutés dans Toolforge/WMCS ou disposant des droits d'utilisateur de bot sur un wiki ne devraient pas être affectés pour le moment. Toutefois, il est conseillé à tous les développeurs de suivre les bonnes pratiques mises à jour. Pour plus d'informations, consultez la page [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|API Wikimedia/Limites de débit]] et la [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits/FAQ|Foire aux questions]]. * L'[[mw:Special:MyLanguage/Attribution API|API d'attribution]] est désormais disponible en [[mw:Special:MyLanguage/Wikimedia APIs/Stability policy|version bêta]]. Elle récupère les informations nécessaires pour créditer les articles et les fichiers multimédias de Wikimedia, quel que soit leur lieu d'utilisation. La documentation de référence est disponible sur la page dédiée au Sandbox REST, accessible sur tous les wikis Wikimedia (comme [https://en.wikipedia.org/w/index.php?api=attribution.v0-beta&title=Special%3ARestSandbox le sandbox REST de Wikipédia en anglais]). N'hésitez pas à partager vos commentaires sur la [[mw:Talk:Attribution API|page de discussion du projet]]. * Il n'y aura pas de nouvelle version de MediaWiki cette semaine. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/17|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W17"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20 avril 2026 à 17:00 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30432763 --> == Request for comment (global AI policy) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies for writing in English. {{int:Please-translate}} A [[:m:Requests for comment/Artificial intelligence policy|request for comment]] is currently being held to decide on a global AI policy. {{int:Feedback-thanks-title}} [[Utilisateur:MediaWiki message delivery|MediaWiki message delivery]] ([[Discussion utilisateur:MediaWiki message delivery|discussion]]) 26 avril 2026 à 02:57 (CEST) </bdi> <!-- Message envoyé par User:Codename Noreste@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30424282 --> == Actualités techniques n° 2026-18 == <section begin="technews-2026-W18"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/18|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * Un changement dans la manière dont les utilisateurs et utilisatrices sont automatiquement confirmés est en cours pour améliorer la protection contre le vandalisme. Actuellement, il suffit d’avoir un compte depuis quelques jours avec quelques contributions pour être ajouté au groupe [[{{int:grouppage-autoconfirmed/{{CONTENTLANGUAGE}}}}|{{int:group-autoconfirmed}}]]. Cette configuration tend à être exploitée par certains vandales qui créent des comptes et commencent à les utiliser après un certain temps. Pour réduire ce problème, la configuration va changer la semaine prochaine afin que l’âge du compte minimum pour être confirmé automatiquement ne soit calculé qu’à partir de la première modification, au lieu de la date d’inscription. L’âge minimum du compte restera le même, c’est seulement le point de départ pour calculer cet âge qui change. Ce changement ne sera déployé que sur les wikis qui nécessitent au moins une contribution pour satisfaire les conditions de confirmation automatique. [https://phabricator.wikimedia.org/T418484] * Tous les utilisateurs et utilisatrices de Wikipédia avec un nouveau compte et ceux qui ont activé l’option « activer automatiquement la plupart des fonctionnalités bêta » peuvent désormais utiliser la fonctionnalité bêta de [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|listes de lecture]] pour enregistrer des articles à lire plus tard. Cela permet d’organiser les lectures qui nous intéressent à un endroit unique pour y accéder facilement. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:30|la tâche soumise|les {{formatnum:30}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:30||s}} la semaine dernière]]. Par exemple, le problème avec les images d’infoboite qui avaient une marge intérieure immense dans Firefox a été corrigé. [https://phabricator.wikimedia.org/T423676] '''Actualités pour la contribution technique''' * Pour rappel, la limite globale d’accès à l’API sera appliquée cette semaine pour identifier le trafic de l’API. Le but est d’aider à garantir un [[mw:MediaWiki Product Insights/Responsible Reuse|accès équitable à l’infrastructure]]. Les robots qui s’exécutent dans Toolforge ou WMCS, ou avec le droit utilisateur ''robot'' sur les wikis, ne devraient pas être affectés pour le moment. Cependant, il est conseillé à tous les développeurs et développeuses de se conformer aux nouvelles bonnes pratiques à suivre. Pour plus d’informations, notamment la limite globale d’accès effective, consultez [[mw:Wikimedia APIs/Rate limits|la page sur la limite d’accès des API de Wikimedia]] et les [[mw:Wikimedia APIs/Rate limits/FAQ|questions-réponses]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.26|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/18|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W18"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 27 avril 2026 à 20:06 (CEST) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30458046 --> == Actualités techniques n° 2026-19 == <section begin="technews-2026-W19"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/19|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L’équipe chargée des fonctionnalités de [[mw:Special:MyLanguage/Article guidance|Guidage des articles]] invite les contributeurs et contributrices expérimentés des [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators|Wikipédia pilotes]] (arabe, bangla, japonais, portugais, persan, turc, anglais simplifié, espagnol et français) à contribuer à la traduction et à l’adaptation des [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Category:Pages_using_article_guidance exemples de trames d’articles]. Ces trames guideront les contributeurs dans la création d’articles clairs, bien structurés et conformes aux règles lors de l’utilisation de [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Special:NewArticle la fonctionnalité] dès son lancement en mai 2026. Des [[mw:Special:MyLanguage/Article guidance#Adapting a sample outline in a Wikipedia|instructions simples]] expliquant comment traduire et adapter ces trames sont disponibles. '''Actualités pour la contribution''' * Le [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif sur les produits et les technologies]] a publié [[:m:Special:MyLanguage/Product and Technology Advisory Council/May 2026 draft PTAC recommendation for feedback|une proposition de recommandation]] d’une procédure type que les organisations affiliées à Wikimedia pourraient suivre pour contribuer au domaine technique. Les membres de la communauté sont invités à donner leur avis sur cette recommandation avant le 8 mai [[:m:Talk:Product and Technology Advisory Council/May 2026 draft PTAC recommendation for feedback|sur la page de discussion]]. * Le nombre de préférences de taille de la miniature disponibles dans MediaWiki va être réduit à trois options standardisées : ''petite'' (180 px), ''moyenne'' (250 px) et ''large'' (400 px), dans le cadre du travail en cours pour améliorer les performances et réduire la pression sur les services de miniatures. Par conséquent, les préférences existantes seront automatiquement adaptées à la nouvelle taille la plus proche (par exemple, les petites tailles comme 120 px ou 150 px s’afficheront à 180 px, tandis que les grandes tailles comme 300 px ou 360 px s’afficheront à 400 px). L’interface des préférences sera bientôt mise à jour pour refléter ces changements, et les utilisateurs qui souhaitent s’y opposer ou donner leur avis peuvent le faire. [https://phabricator.wikimedia.org/T424909] * Dorénavant, même lorsqu’une permission expire automatiquement, les utilisateurs recevront une notification Echo similaire à la notification normale pour les changements de permissions. Quant au [[m:Special:MyLanguage/Global reminder bot|robot global de rappel]], il continue de prévenir les utilisateurs une semaine ''avant'' que leurs droits ne soient sur le point d’expirer, afin qu’ils puissent les faire renouveler. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:32|la tâche soumise|les {{formatnum:32}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:32||s}} la semaine dernière]]. Par exemple, le problème du sélecteur de langue ULS dans [[m:Special:Translate|Special:Translate]] qui faisait défiler verticalement alors qu’il ne devait pas, a été résolu. Auparavant, lorsque les utilisateurs ouvraient le menu déroulant « Traduire en français » et commençaient à saisir le nom d’une langue, la boîte de dialogue défilait verticalement de quelques pixels même lorsqu'il y avait suffisamment d’espace pour afficher tous les résultats. Le menu déroulant ne se déplace plus inutilement lors du filtrage des langues. [https://phabricator.wikimedia.org/T358864] * La [[m:Special:GlobalWatchlist|liste de suivi globale]], qui vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page, continue de s’améliorer. Par exemple, les listes de suivi pour les sites avec Wikibase tels que [[:d:|Wikidata]] prennent désormais en charge les éléments [[mw:Special:MyLanguage/Extension:EntitySchema|EntitySchema]] pour un meilleur suivi. Le mode Mises à jour en direct actualise désormais la page spéciale toutes les 60 secondes afin de se conformer aux [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|nouvelles limites globales d’accès à l’API]] pour une meilleure réactivité en temps réel. Par ailleurs, un bug de directionnalité du texte qui affichait les liens comme « changements 3 » au lieu de « 3 changements » dans les listes à directions mixtes a été corrigé. [https://phabricator.wikimedia.org/T415450][https://phabricator.wikimedia.org/T424422][https://phabricator.wikimedia.org/T418091] '''Actualités pour la contribution technique''' * La deuxième phase de [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|limitations globales d’accès à l’API]] a été déployée pour réduire l’[[diffblog:2026/03/26/quo-vadis-crawlers-progress-and-whats-next-on-safeguarding-our-infrastructure/|impact des robots IA]] et assurer un accès équitable et durable aux ressources de Wikimedia, en donnant la priorité au trafic humain et conforme à notre mission. Les [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits#Limits|limites]] ne s’appliquent plus par heure mais par minute, produisant une meilleure répartition dans les structures de trafic ainsi qu’une meilleure prévisibilité de la charge de l’API. Les utilisateurs de la communauté ne devraient pas être affectés, et aucune action n’est requise. Les premières indications montrent que certains requérants basés sur l'agent utilisateur ajustent leur comportement, et environ 64 % du trafic API automatisé a été identifié. La surveillance continue, et Wikimedia Enterprise reste disponible pour l’assistance commerciale. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.27|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/19|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W19"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 4 mai 2026 à 22:43 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30498077 --> == Actualités techniques n° 2026-20 == <section begin="technews-2026-W20"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/20|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * La Communauté Technique a publié [[m:Special:MyLanguage/Community Wishlist/How to write a good wish|de nouvelles directives]] expliquant comment les souhaits sur la Liste de souhaits de la communauté sont triés et priorisés. La documentation vise à aider les contributeurs à rédiger des propositions plus solides en clarifiant les facteurs qui influencent les décisions de priorisation. Au-delà du nombre de votes, les directives mettent en avant des considérations telles que l'impact potentiel sur la communauté pour déterminer quels souhaits avanceront. '''Actualités pour la contribution''' * L'équipe de croissance des lecteurs lance une expérience pour tester une nouvelle [[mw:Special:MyLanguage/Readers/Reader_Growth/Share_Card|fonctionnalité de Partage de Carte]] qui permet aux lecteurs de créer des cartes visuellement attrayantes à partir d'articles Wikipédia ou de sections d'articles sélectionnées et de les partager en ligne, chaque carte renvoyant à l'article original afin d'aider à augmenter le lectorat et la découverte des articles. Le test A/B réservé aux mobiles ne sera disponible qu'à une partie des lecteurs sur les Wikipédia en arabe, chinois, français, vietnamien et anglais afin de mieux comprendre les habitudes de lecture et de partage, et est prévu pour commencer la semaine du 18 mai pour une durée de quatre semaines. * Les applications Wikipedia pour Android et iOS ont récemment publié en version bêta le [[mw:Special:MyLanguage/Wikimedia_Apps/Team/25th_Birthday_Reading_Challenge|défi de lecture de 25 jours]], dans le cadre des efforts visant à stimuler l'engagement des lecteurs en encourageant les utilisateurs à atteindre des objectifs de lecture. Pour suivre leur série de lectures pendant le défi, les utilisateurs de l'application peuvent ajouter un widget avec Baby Globe à leur écran d'accueil. Le défi commence officiellement le 11 mai. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:17|la tâche soumise|les {{formatnum:17}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:17||s}} la semaine dernière]]. Par exemple, un problème où la préférence globale pour activer la coloration syntaxique dans le wikitexte pouvait s'éteindre de manière inattendue après avoir été activée a maintenant été corrigé. [https://phabricator.wikimedia.org/T425286] '''Actualités pour la contribution technique''' * [[File:Octicons-tools.svg|12px|link=|alt=|Sujet technique]] Le module ResourceLoader <bdi lang="zxx" dir="ltr"><code><nowiki>mediawiki.ui.input</nowiki></code></bdi>, obsolète depuis [[m:Special:MyLanguage/Tech/News/2023/39|septembre 2023]], sera supprimé cette semaine. Il existe un [[mw:Special:MyLanguage/Codex/Migrating_from_MediaWiki_UI|guide pour migrer de l’interface MediaWiki UI vers Codex]] pour tous les outils qui l’utilisent. [https://phabricator.wikimedia.org/T420125] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.2|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/20|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W20"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 11 mai 2026 à 21:20 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30524429 --> == Actualités techniques n° 2026-21 == <section begin="technews-2026-W21"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/21|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L'équipe de Wikipédia abstraite a identifié cinq wikis pilotes potentiels pour évaluer leur intérêt à adopter des articles abstraits sur leurs wikis. Les pilotes sont Wikipédia en Malayalam, en Bengali, en Dagbani, en Arabe et en Indonésien. La période de retour d'information sera ouverte jusqu'au 22 mai. Si votre communauté est intéressée à devenir un pilote, [[m:Talk:Abstract Wikipedia|faites-nous savoir sur Meta]]. '''Actualités pour la contribution''' * Une expérience visant à afficher [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|les listes de lecture]] aux lecteurs non connectés sur le web mobile sera lancée le 18 mai sur les Wikipédias Allemande, Espagnole, Italienne, Portugaise, Polonaise, Néerlandaise, Turque et Ourdou, et durera un mois. Cet effort soutient des objectifs plus larges consistant à aider les lecteurs à enregistrer et organiser des articles pour une lecture ultérieure, tout en encourageant des habitudes qui pourraient mener à de futures contributions sur Wikipédia. * Pour prendre en charge un bouton de marquage dans la fonctionnalité bêta Liste de lecture, le menu "Outils > Action" a été mis à jour pour afficher des icônes, y compris l'indicateur en forme d'étoile de suivi qui aide les éditeurs à identifier les articles suivis temporairement. Les icônes correspondent désormais également à celles utilisées sur mobile, améliorant la cohérence entre les plateformes. Le changement est actuellement limité au menu des actions et concerne principalement les éditeurs ayant des droits d'utilisateur privilégié. [https://phabricator.wikimedia.org/T426008] * [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Mode de Suggestion]] a été publié en tant qu'[[w:en:A/B test|test A/B]] pour les nouveaux éditeurs sur le site mobile à [[phab:T421189|~15 Wikipédias]]. L'expérience mesurera l'impact que le Mode de Suggestion a sur la proportion de sessions d'édition sur le web mobile par des nouveaux éditeurs qui aboutissent à des modifications constructives (non annulées) des articles. L'expérience évaluera également l'impact de la fonctionnalité sur la rétention des éditeurs et surveillera les changements dans les taux d'annulation et de blocage. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, un problème dans l'application Android de Wikipédia où les images pourraient parfois ne pas se charger après avoir ouvert une notification de liste de lecture recommandée, a maintenant été corrigé. [https://phabricator.wikimedia.org/T418231] '''Actualités pour la contribution technique''' * L'[[mw:Special:MyLanguage/Wikidata Platform|équipe de la Plateforme Wikidata]] a publié sa [[d:Special:MyLanguage/Wikidata:SPARQL query service/WDQS backend update/Backend Replacement|recommandation de remplacement du backend]] et l'[[wikitech:Wikidata Query Service/WDQS Architecture re-design|architecture technique]] qui l'accompagne pour la migration du Wikidata Query Service (WDQS) hors de Blazegraph grap. Les retours sont attendus jusqu'au 25 mai 2026, en particulier sur les éventuelles lacunes et impacts sur les cas d'utilisation avancés. Les membres de la communauté Wikidata et les utilisateurs de WDQS sont également encouragés à aider à identifier les outils et flux de travail à fort impact qui pourraient nécessiter une attention sur [[d:Wikidata:SPARQL query service/WDQS backend update/High-Impact Use Cases|cette page]]. Les retours peuvent être partagés sur la [[d:Wikidata talk:SPARQL query service/WDQS backend update|page de discussion de la migration]] ou lors de la [[d:Special:MyLanguage/Wikidata:Blazegraph Migration Office Hours|prochaine heure de bureau]]. Voir le [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|bulletin de l'équipe WDP]] pour plus de détails. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.3|MediaWiki]] '''En détails''' * Sur les Wikipédia en anglais, en français, en japonais et quelques autres, il y a eu un [[diffblog:2025/09/02/better-detecting-bots-and-replacing-our-captcha/|essai de hCaptcha]], un service tiers de détection de robots. L'essai a montré que hCaptcha détecte et dissuade efficacement certaines activités automatisées de mauvaise foi, à la fois par lui-même et en donnant des signaux aux [[w:en:Wikipedia:Village pump (technical)/Archive 225#Introducing SuggestedInvestigations|checkusers et stewards]] pour qu'ils enquêtent. Comme les résultats étaient positifs, hCaptcha sera déployé sur toutes les wikis au cours des prochaines semaines. [[mw:Special:MyLanguage/Product Safety and Integrity/Anti-abuse signals/hCaptcha|Voir la page du projet hCaptcha]] pour des informations techniques sur la mise en œuvre et les protections de la vie privée. [[diffblog:2026/05/04/better-detecting-bots-and-replacing-our-captcha-part-2/|En savoir plus]]. * La dernière mise à jour de la Technologie communautaire est désormais disponible, avec des progrès dans plusieurs initiatives de la Liste de souhaits communautaire, y compris l'extension des listes de lecture de l'application mobile au site web, la prise en charge de nouvelles langues pour "Who Wrote That" et le Tableau de bord personnel, des améliorations du rendu 3D et des graphiques, ainsi que des travaux à venir sur le tri des pages de discussion, la lecture audio et les flux de travail d'édition. La mise à jour partage également les priorités actuelles, les tendances de l'état de la Liste de souhaits et les opportunités de retour d'information de la communauté sur les domaines de concentration futurs et le Plan annuel 2026–2027 de la Wikimedia Foundation. [[m:Special:MyLanguage/Community Wishlist/Updates#May 13, 2026: Latest updates from the Community Tech team|Lisez le bulletin d'information complet pour plus de détails]]. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/21|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W21"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 18 mai 2026 à 22:21 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30539262 --> == Actualités techniques n° 2026-22 == <section begin="technews-2026-W22"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/22|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Faisant suite à une [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#LOWM|expérience fructueuse sur la création de comptes]], un message d'avertissement pour les personnes déconnectées sera déployé sur les wikis Wikimédia durant la première semaine de juin. Ce changement n'affectera que les personnes déconnectées sur l'interface web mobile qui commencent à modifier. Cette nouvelle expérience est faite pour encourager la création de comptes, tout en autorisant aux utilisateurs de modifier à l'aide de comptes temporaires. Les résultats de l'expérience ont montré une augmentation de la création de compte d'environ 27 % pour ceux ayant vu le nouveau message. Comme prévu, puisque plus de personnes créent un compte, la création de comptes temporaires a diminué de 16 %. L'expérience n'a pas montré d'autres changements sur la qualité des modifications ou sur les autres indicateurs surveillés. [https://phabricator.wikimedia.org/T424595] '''Actualités pour la contribution''' * Pour des raisons de sécurité, les membres de certains groupes d’utilisateurs sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir l'authentification à 2 facteurs]] (A2F) d'activée. Les membres de ces groupes seront dans l'impossibilité de désactiver la dernière méthode d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Ces utilisateurs auront toujours la possibilité d'ajouter ou d'enlever des nouvelles méthodes d'authentification, tant qu'une de ces méthodes est toujours activée. Dans les prochaines semaines, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique entre autres aux bureaucrates. Veuillez lire les tâches liées pour les dates de déploiement. [https://phabricator.wikimedia.org/T423119][https://phabricator.wikimedia.org/T423120] * L'[[m:Special:MyLanguage/WMDE Technical Wishes|équipe des souhaits techniques de Wikimédia Allemagne (WMDE)]] va lancer un [[w:fr:Test A/B|test A/B]] sur [[:phab:T415904|10 wikis]], pour essayer des [[m:WMDE Technical Wishes/References/Reference Previews|améliorations potentielles pour les aperçus de références]]. Cette expérience durera environ 2 semaines à la fin mai ou début juin et affectera 10 % du lectorat sur ordinateur sur les wikis participants. * Après deux expériences fructueuses, l'équipe Croissance du lectorat déploiera une fonctionnalité de [[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|visionnage d'images]] en bêta pour toutes les Wikipédia sur mobile le 25 mai. Cela veut dire que toutes les personnes ayant les fonctionnalités bêtas activées verront cette fonctionnalité. Les autres pourront l’activer dans leurs préférences. Cette fonctionnalité inclura un carrousel de toutes les images d'un article en haut de celui-ci, avec la possibilité pour les contributeurs d’[[mw:Readers/Reader_Growth/Image_Browsing#Phase_2.1_beta_feature|exclure des images du carrousel d'un article ou d'enlever la fonctionnalité pour l'entièreté de l'article]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:30|la tâche soumise|les {{formatnum:30}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:30||s}} la semaine dernière]]. Par exemple, les fichiers STL tridimensionnels étaient affichés incorrectement par l'extension 3D du lecteur multimédia, ce qui est maintenant corrigé. [https://phabricator.wikimedia.org/T416723] '''Actualités pour la contribution technique''' * Les classes CSS dépréciées <bdi lang="zxx" dir="ltr"><code><nowiki>tleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>tright</nowiki></code></bdi> ont été remplacées par <bdi lang="zxx" dir="ltr"><code><nowiki>floatleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>floatright</nowiki></code></bdi> car les premières ne fonctionnent pas correctement sur toutes les plateformes, dont l'interface web mobile et l'application mobile. Les projets se servant de ces classes sont encouragés à vérifier leur usage et à planifier leur migration. Sachez que <bdi lang="zxx" dir="ltr"><code><nowiki>floatleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>floatright</nowiki></code></bdi> pourraient aussi être dépréciées dans le futur, même s’il n'y a pas de calendrier défini. [[phab:T426452|En savoir plus]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.4|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/22|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W22"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 25 mai 2026 à 23:52 (CEST) <!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30584502 --> == Votez maintenant aux élections 2026 de l'U4C == <section begin="announcement-content" /> Les votants éligibles sont invités à participer à l'élection 2026 du [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Comité de coordination du Code de conduite universel]]. De plus amples informations – notamment sur la vérification de l'éligibilité, le processus de vote, les candidats et un lien vers le scrutin – sont disponibles sur Meta à la [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|page d'informations sur les élections de 2026]]. Le scrutin se termine le 2 juin 2026 à [https://zonestamp.toolforge.org/1780358400 00 h 00 UTC]. Veuillez voter si votre compte est éligble. Les résultats seront disponibles avant le 14 juin 2026. -- en coopération avec l'U4C.<section end="announcement-content" /> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 27 mai 2026 à 19:14 (CEST) <!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Actualités techniques n° 2026-23 == <section begin="technews-2026-W23"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/23|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * L'équipe [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience]] mène une expérience pour montrer la fonctionnalité [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|listes de lecture]], qui est encore en développement, aux lecteurs non connectés sur mobile afin de tester si elle encourage la création de compte à un rythme plus élevé que le bouton watchstar. L'[[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists#Experiment timeline|expérience]] a été lancée le 18 mai sur les wikis en allemand, espagnol, italien, portugais, polonais, néerlandais, turc et ourdou, et elle durera un mois. * L'équipe Wikimedia Apps a publié la [[mw:Special:MyLanguage/Wikimedia Apps/Team/Explore Feed Refresh/Phase 1|Phase 1]] du flux d'accueil repensé pour l'application Android Beta. Le nouveau flux d'accueil comprend un onglet « Communauté » actualisé et un onglet « Pour vous » personnalisé contenant des recommandations de lecture mises à jour quotidiennement. La refonte fait partie d'un effort plus large visant à améliorer la découverte de contenu et à créer des expériences d'apprentissage plus engageantes dans les applications Wikipédia. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:18|la tâche soumise|les {{formatnum:18}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:18||s}} la semaine dernière]]. Par exemple, un problème où les images pouvaient ne pas se charger pour certaines modifications suggérées sur [[w:Special:Homepage|Special:Homepage]], laissant la vignette bloquée dans un état de chargement, a maintenant été corrigé. [https://phabricator.wikimedia.org/T424048] '''Actualités pour la contribution technique''' * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.5|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/23|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W23"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 1 juin 2026 à 23:08 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30613639 --> == Actualités techniques n° 2026-24 == <section begin="technews-2026-W24"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/24|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Wikimedia Entreprise a relevé les limites d’utilisation gratuite de ses API. La limite mensuelle de requêtes pour l’API « à la demande » (<i lang="en">On-demand</i>) est passée de {{formatnum:5000}} à {{formatnum:50000}} requêtes, tandis que celle de l’API des instantanés (<i lang="en">Snapshot</i>) est passée de 15 à 30 requêtes par mois. De plus, les instantanés de contenus structurés sont désormais accessibles aux comptes gratuits. Ces changements élargissent l’accès aux données de Wikimedia Entreprise pour les développeurs et développeuses, les chercheurs et chercheuses et les organisations qui utilisent les contenus Wikimédia. [https://enterprise.wikimedia.com/blog/enhanced-free-api] '''Actualités pour la contribution''' * La [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Explore Feed Refresh/Phase 1|nouvelle version du Fil d’exploration]], désormais appelé « Fil d’accueil », est en cours de déploiement auprès de 50 % des utilisateurs de l’application Wikipédia pour Android. Le fil d’accueil aide le lectorat à découvrir du contenu pertinent grâce à deux nouveaux onglets : « Communauté » et « Pour vous ». L’onglet « Communauté » propose un flux défilant de contenus sélectionnés et d’actualités provenant de l’ensemble de la communauté et du mouvement Wikimédia, tandis que l’onglet « Pour vous » offre une expérience en plein écran et par glissement qui présente des contenus adaptés aux centres d’intérêt de l’utilisateur ou utilisatrice. Cette refonte s’inscrit dans le cadre d’un travail en cours visant à améliorer la découverte et à enrichir l’expérience d’apprentissage au sein de l’application Wikipédia. * Le jeu-questionnaire quotidien [[mw:Special:MyLanguage/Wikimedia Apps/Team/iOS/"Which came first?" Game|Qu’est-ce qui est arrivé en premier ?]] est désormais disponible dans la version bêta de l’application Wikipédia pour iOS en anglais, allemand, français, portugais, russe, espagnol, arabe, chinois et turc. Le jeu s’appuie sur des événements historiques tirés de la rubrique « Éphéméride » de Wikipédia et met les lecteurs au défi de deviner lequel des deux événements s’est produit en premier. Le jeu avait déjà été lancé sur Android. Les communautés souhaitant rendre le jeu disponible dans leur langue peuvent [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Games#Game availability by language|consulter les instructions et les conditions requises]]. * [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|Les sous-références]], une nouvelle fonctionnalité de MediaWiki permettant aux contributeurs de réutiliser des références avec des détails différents, va commencer à être déployée sur les wikis Wikimédia après une phase pilote réussie. Le déploiement débutera le 8 juin pour la plupart des [[wikitech:Deployments/Train#Wednesday|wikis du groupe 1]] et Wikipédia en français, puis d'autres éditions linguistiques de Wikipédia bénéficieront de cette fonctionnalité au cours des prochains mois. Les communautés sont invitées à se préparer en vérifiant s’il existe des [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-cite&language=en&action_source=search&filter=%21translated&optional=1&action=translate messages non traduits de l’extension Cite] dans leur langue et en passant en revue toute utilisation de l’outil [[mw:Special:MyLanguage/Reference Tooltips|Infobulles des références]], qui pourraient nécessiter des [[:phab:T416304#11668731|mises à jour]] pour prendre en charge la nouvelle fonctionnalité. Les wikis utilisant les [[mw:Special:MyLanguage/Help:Reference Previews|aperçus de référence]] n’ont aucune action à entreprendre. Les communautés peuvent également créer la [[Special:TrackingCategories|catégorie de suivi]] ''cite-tracking-category-ref-details'' en tant que catégorie cachée à l’aide de <code><nowiki>__HIDDENCAT__</nowiki></code> (ou d’un modèle dédié), et la relier à l’élément Wikidata correspondant [[d:Q129764848]]. [https://phabricator.wikimedia.org/T425662] * L'[[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews#Experimentation|expérience d'Aperçus de page]] sur le Web mobile a pris fin. L'équipe a décidé de ne pas déployer cette fonctionnalité après que les résultats ont montré qu'elle n'avait pas d'impact statistiquement significatif sur la fidélisation des lecteurs, l'amélioration de la fidélisation étant le principal indicateur de réussite. Les « Aperçus de page », déjà disponibles sur ordinateur et dans les applications, affichent une vignette, le premier paragraphe et un lien vers l'article complet lorsque les lecteurs cliquent sur un lien bleu. L'expérience a testé cette fonctionnalité sur le Web mobile sur six versions de Wikipédia. * La [[mw:Special:MyLanguage/Codex/Design/Icons|bibliothèque d'icônes de l'interface utilisateur]] sera [[phab:T399175|mise à jour dans le courant de cette semaine ou la semaine prochaine]]. La plupart des quelque 300 icônes ont été légèrement peaufinées et une trentaine de nouvelles icônes ont été ajoutées. Ces modifications améliorent les icônes afin de les rendre plus cohérentes et plus compréhensibles, et d'offrir un meilleur équilibre visuel lorsqu'elles sont utilisées en groupe. * L'interface [[mw:Special:MyLanguage/Universal Language Selector|Sélecteur universel de langue]] (ULS) de MediaWiki, qui aide les utilisateurs à sélectionner du contenu dans d'autres langues, a été mise à jour. La nouvelle version améliore la rapidité et l'accessibilité, et les utilisateurs des projets Wikimédia peuvent désormais épingler des langues pour changer de langue plus rapidement. Le déploiement sur les sites Wikimédia se fera progressivement au cours des prochaines semaines. Vous pouvez la tester dès maintenant en tant que fonctionnalité bêta en sélectionnant [[Special:Preferences#mw-prefsection-betafeatures|les fonctionnalités bêta]] dans les préférences de votre profil et partager vos commentaires sur [[mw:Special:MyLanguage/Universal Language Selector/New ULS|la page du projet]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:21|la tâche soumise|les {{formatnum:21}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:21||s}} la semaine dernière]]. Par exemple, un problème du le tableau de bord d'analyse des pages vues sur pageviews.wmcloud.org qui a arrêté de mettre à jour les données graphiques en mai 2026, affectant tous les utilisateurs, a été résolu. [https://phabricator.wikimedia.org/T427171] '''Actualités pour la contribution technique''' * La signature de la fonction <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink()</nowiki></code></bdi> a été simplifiée. Les développeurs peuvent désormais passer un objet de configuration à la place d'une liste de paramètres positionnels lors de la création de liens vers des portlets. L'ancienne signature de la fonction reste prise en charge à des fins de compatibilité ascendante. Par exemple, au lieu de : <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', '#', 'Stub', 'ca-stubtag', 'Add a stub tag to this page');</nowiki></code></bdi>, utilisez <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', { href: '#', text: 'Stub', id: 'ca-stubtag', tooltip: 'Add a stub tag to this page' });</nowiki></code></bdi>. Les responsables de la maintenance des scripts sont invités à passer en revue les utilisations existantes de <bdi lang="zxx" dir="ltr"><code><nowiki>addPortletLink()</nowiki></code></bdi> et à les mettre à jour si nécessaire. Cette modification sera disponible sur tous les wikis à partir du 11 juin. Merci à Gerges, bénévole de la communauté, d'avoir apporté cette amélioration. [https://phabricator.wikimedia.org/T427945] * '''Discussion sur la liste de souhaits de la communauté''': les [[m:Special:MyLanguage/Community Wishlist/Updates#May 20, 2026: Community Tech becomes a program|changements introduits]] par les équipes Produit et Technologie visent à augmenter le nombre et la complexité des souhaits exaucés, notamment par la dissolution de l'équipe Community Tech. Ils [[m:Special:MyLanguage/Community Wishlist/Updates|mènent actuellement des discussions]] sur une [[m:Talk:Community Wishlist#Proposed direction for Wishlist|orientation proposée pour la liste de souhaits]] émanant des membres de la communauté. Cela inclut des moyens de structurer le vote annuel, un meilleur suivi des souhaits, la suppression de certains domaines prioritaires et des [[m:Special:MyLanguage/Community Wishlist/Updates|mises à jour concernant le personnel]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.6|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/24|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W24"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 8 juin 2026 à 23:29 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30650573 --> == Actualités techniques n° 2026-25 == <section begin="technews-2026-W25"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/25|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L'[[mw:Special:MyLanguage/Readers/Reader Growth|équipe chargée de la croissance du lectorat]] a lancé une fonctionnalité bêta d'[[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|exploration des images]] sur la version mobile de toutes les Wikipédias. Cette fonctionnalité affiche un carrousel d'images en haut des articles contenant au moins trois images. Les contributeurs peuvent configurer cette fonctionnalité à l'aide des commandes suivantes : pour masquer une image spécifique sur une page, utilisez soit <code>class=notpageimage</code> pour l'exclure des aperçus miniatures, soit <code>class=noviewer</code> pour l'exclure de MediaViewer. Le carrousel peut également être désactivé complètement sur une page à l'aide du mot magique <code><nowiki>__NOMEDIAVIEWERCAROUSEL__</nowiki></code>. Pour faire des retours ou signaler des bugs, rendez-vous sur la [[mw:Talk:Readers/Reader Growth/Image Browsing|page de discussion du projet]]. * Les [[mw:Special:MyLanguage/Help:Tables#class="wikitable"|Wikitables]] peuvent désormais être [[mw:Special:MyLanguage/Help:Sortable tables#Forcing the initial sort direction|triées par ordre décroissant]] dès le premier clic en ajoutant <code dir=ltr>data-sort-order="desc"</code> à la cellule d'en-tête. Auparavant, par défaut, cliquer une première fois sur l'en-tête d'une colonne entraînait un tri par ordre croissant. Cette nouveauté offre davantage de contrôle et de flexibilité pour les Wikitables, tandis que le comportement par défaut pour les clics suivants reste inchangé. [https://phabricator.wikimedia.org/T398416] '''Actualités pour la contribution''' * La fonctionnalité d'[[mw:Special:MyLanguage/Article guidance|Aide à la rédaction d'articles]] est actuellement en phase de test auprès de certains contributeurs qui créent de nouveaux articles sur les Wikipédias en anglais simplifié, en français et en turc. L'expérience débutera bientôt sur les Wikipédias en arabe et en bengali également. [[w:simple:Special:NewArticle|Cette fonctionnalité]] fournit aux contributeurs des conseils élaborés par la communauté afin de les aider à créer des articles conformes aux normes communautaires. Les contributeurs expérimentés peuvent continuer à créer ou à adapter des modèles pour des types d'articles spécifiques qui sont couramment créés par des contributeurs moins expérimentés. Ces modèles guident les contributeurs moins expérimentés dans la création d'articles de haute qualité. Un guide rapide des balises utilisées dans les modèles est disponible sur [[mw:Special:MyLanguage/Article guidance/Test feature guide#Markups in outlines|cette page]]. [[w:fr:Projet:Aide à la rédaction d'articles#Liste de plans d'aide à la rédaction|Des exemples de modèles]] pouvant être adaptés, ainsi que des instructions sur la manière de les adapter, se trouvent dans [[mw:Special:MyLanguage/Article guidance#Adapting a sample outline in a Wikipedia|cette section]] de la page du projet. * Les wikis qui souhaitent remplacer le bouton « indéfiniment » dans la page Special:Block pour les comptes temporaires (par exemple, les wikis qui bloquent les utilisateurs temporaires uniquement jusqu'à l'expiration de leur compte) pourront le faire en créant [[MediaWiki:ipb-indefinite-expiry-temporary-account]] avec la durée de blocage souhaitée. [https://phabricator.wikimedia.org/T427125] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:41|la tâche soumise|les {{formatnum:41}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:41||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * D'ici la fin du mois de juin, une chaîne « user-agent » valide sera requise pour les téléchargements automatisés de sauvegardes depuis le site dumps.wikimedia.org. Les requêtes automatisées fournissant une chaîne « user-agent » générique ou vide seront bloquées. Cette mesure [[phab:T400119|renforce l'application]] de la [[foundation:Special:MyLanguage/Policy:Wikimedia Foundation User-Agent Policy|politique relative à l'agent utilisateur]] en vigueur depuis longtemps. L'accès aux sauvegardes via Wikimedia Cloud Services restera inchangé. * La mise en place des [[mw:Wikimedia APIs/Rate limits|limites de débit des API]] à l'échelle mondiale est désormais achevée ; ces limites s'appliquent à toutes les API et sont fixées aux niveaux indiqués dans la documentation pour tous les groupes. Les bots fonctionnant sur Toolforge/WMCS ou disposant du droit d'utilisateur « bot » sur n'importe quel wiki restent exemptés. Tous les bots doivent continuer à respecter les bonnes pratiques décrites dans la documentation afin d'éviter d'être soumis à des limites de débit. * Le [https://api.wikimedia.org/wiki/Main_Page wiki du portail API] sera en lecture seule à partir de cette semaine (du 15 au 18 juin). La semaine suivante (du 22 au 25 juin), toutes les URL du wiki du portail API redirigeront vers [[mw:Wikimedia APIs|les API Wikimedia sur mediawiki.org]]. Pour en savoir plus, consultez la [[wikitech:API Portal/Deprecation|page du projet]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.7|MediaWiki]] '''Rencontres et évènements''' * Le 17 juin à 18 h (UTC), la WMF organisera une réunion sur Discord consacrée à la revue de code. L'[[mw:Special:MyLanguage/Developer Satisfaction Survey/2026|enquête sur la satisfaction des développeurs]] nous a permis de constater que les bénévoles rencontrent des difficultés avec la revue de code, et nous souhaitons discuter de ces expériences afin de trouver des solutions concrètes. Vous pouvez rejoindre la réunion [https://discord.gg/wikipedia?event=1514727511102062664 via le serveur Discord de la communauté Wikimedia]. * La [[m:Special:MyLanguage/Conferencia Wikimedia de América Latina 2026|Conférence Wikimedia d'Amérique latine]] organisera un hackathon régional qui réunira la communauté technique du mouvement Wikimedia, notamment des développeurs, des administrateurs système, des data scientists et des utilisateurs disposant de droits étendus. Les contributeurs techniques intéressés peuvent [https://docs.google.com/forms/d/e/1FAIpQLSf4osJzTHBJjQbYJk7TMVEJjTEQv7IgtsUDfP-o-qTgeRQQxw/viewform postuler à une bourse] pour y participer jusqu'au 21 juin à minuit (heure de la Bolivie, UTC-4). * Inscrivez-vous aux Wikimania Team Challenges pour participer à cet événement exceptionnel. Les défis par équipe se dérouleront en ligne et en présentiel les 21 et 22 juillet, avant la conférence Wikimania. Tout le monde est le bienvenu, quelles que soient ses compétences ou son inscription à Wikimania. Les équipes travailleront sur 10 défis importants visant à soutenir la communauté Wikimedia. Pour plus de détails, rendez-vous sur [[wmania:Special:MyLanguage/2026:Team challenges|la page des défis par équipe]] et [https://wikimedia.eventyay.com/wm/teamchallenges/ inscrivez-vous ici]. Les inscriptions se terminent le 20 juin à 23 h UTC. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/25|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W25"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 15 juin 2026 à 18:48 (CEST) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30689604 --> == Actualités techniques n° 2026-26 == <section begin="technews-2026-W26"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/26|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Les [[mw:Special:MyLanguage/Growth/Feature summary|fonctionnalités de croissance]] sont [[phab:T418115|désormais disponibles sur Wikidata]]. Cette mise à jour permet d'accéder au mentorat ([[mw:Special:MyLanguage/Help:Growth/Mentorship|s'il est configuré]]), au module Impact, au panneau d'aide et à une page d'accueil simplifiée pour les nouveaux arrivants (sans les suggestions de modifications). Les administrateurs de Wikidata continuent de paramétrer ces fonctionnalités via la configuration communautaire. '''Actualités pour la contribution''' * La page spéciale [[{{#special:RangeCalculator}}]] a été créée. Elle permet aux utilisateurs de trouver une plage d'adresses IP sans avoir à recourir à des outils externes. Jusqu'à présent, cet outil n'était accessible qu'aux CheckUsers. [https://phabricator.wikimedia.org/T268429] * Les [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-références]] sont une nouvelle fonctionnalité de MediaWiki qui permet aux contributeurs de réutiliser des références en modifiant certains détails. Elle sera déployée le 23 juin, sur la plupart des versions de Wikipédia de petite et moyenne taille. La [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#deployment|FAQ]] répertorie les mesures à prendre sur votre wiki pour faciliter ce déploiement. Consultez le [[:phab:T414094|plan de déploiement]] pour connaître les prochaines étapes. [https://phabricator.wikimedia.org/T428902] * À partir de la semaine prochaine, les utilisateurs recevront une notification lorsqu'ils seront bloqués ou débloqués pour l'édition, ou si ce blocage venait à changer. [https://phabricator.wikimedia.org/T100974] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:32|la tâche soumise|les {{formatnum:32}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:32||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * À partir de la semaine prochaine, les filtres anti-abus configurés pour « exiger une vérification par CAPTCHA » s'appliqueront également aux utilisateurs disposant du droit <code>skipcaptcha</code>, ce qui inclut la plupart des utilisateurs auto-confirmés. Les bots en sont exemptés. Ce changement ne concerne que les modifications qui déclenchent un filtre anti-abus. Le droit <code>skipcaptcha</code> continuera à exempter les utilisateurs de l'obligation de résoudre des CAPTCHA dans le cadre d'une utilisation normale des wikis. [https://phabricator.wikimedia.org/T402595] * La documentation de référence relative à l'[[wikitech:Machine_Learning/LiftWing/API|API Lift Wing]] a été déplacée du portail API vers le [https://wikitech.wikimedia.org/w/index.php?api=lift-wing&title=Special%3ARestSandbox bac à sable REST] interactif. * Le wiki du Portail API est désormais fermé. Pour consulter la documentation relative aux API, rendez-vous sur [[mw:Special:MyLanguage/Wikimedia_APIs|Wikimedia APIs sur mediawiki.org]]. À compter du 22 juin, toutes les URL du wiki du Portail API (https://api.wikimedia.org/wiki/) redirigeront vers la page de mediawiki.org. [https://phabricator.wikimedia.org/T427537] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.8|MediaWiki]] '''Rencontres et évènements''' * Participez à une visioconférence le 25 juin à 14 h 30 UTC pour rencontrer les stagiaires actuels de Wikimédia participant au [[mw:Google_Summer_of_Code/2026|Google Summer of Code]] et à [[mw:Outreachy/Round_32|Outreachy]]. Les stagiaires présenteront leurs projets et feront une brève démonstration du travail qu'ils ont réalisé jusqu'à présent. Les participants sont invités à [[mw:event:Google_Summer_of_Code/Summer_2026_June_Internship_open_session|partager leurs idées et leurs contacts au sein de leur communauté]]. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/26|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W26"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 juin 2026 à 15:05 (CEST) <!-- Message envoyé par User:Trizek (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30722494 --> iio27pf4iykw6g1zq4816uib458a094 768431 768401 2026-06-23T17:11:22Z MediaWiki message delivery 36013 /* RFC about AI-generated content in Wikimedia Commons */ nouvelle section 768431 wikitext text/x-wiki == Actualités techniques n° 2026-03 == <section begin="technews-2026-W03"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/03|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * La Fondation Wikimedia a publié des questions directrices pour son plan annuel de juillet 2026 à juin 2027 sur les plateformes [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] et ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. Celles-ci portent sur les tendances mondiales, une expérimentation plus rapide et plus constructive, un meilleur accompagnement des nouveaux contributeurs, le renforcement du rôle des éditeurs et des utilisateurs avancés, l'amélioration de la collaboration entre les projets, ainsi que le développement et la fidélisation du lectorat. Des commentaires et suggestions sont les bienvenus sur la [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|page de discussion]]. '''Actualités pour la contribution''' * Dans le cadre des travaux en cours de l'équipe technique communautaire sur le projet [[m:Special:MyLanguage/Community Wishlist/W372|Listes de surveillance multiples]], l'affichage de [[Special:EditWatchlist|Modifier la liste de surveillance]] sera mis à jour entant que qu'une première étape vers la prise en charge de plusieurs listes de surveillance. De plus, la pagination de [[Special:Search|Recherche]] sera également mise à jour, dans le cadre du travail sur le souhait [[m:Special:MyLanguage/Community Wishlist/W186|Refonte de la pagination / navigation des pages]]. [https://phabricator.wikimedia.org/T411596] * [[m:Special:GlobalWatchlist|La Liste de Surveillance Globale]] est une [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] de MediaWiki qui vous permet de voir vos listes de surveillance provenant de différents wikis sur la même page. Il a récemment été mis à jour pour ressembler davantage à la [[Special:Watchlist|Liste de surveillance]] régulière, par exemple en le préparant pour les comptes temporaires dans le masquage IP (y compris le réacheminement des liens des utilisateurs vers les pages de contributions), en mettant les titres de page en gras et en ouvrant les liens dans les résumés d'édition et les balises dans de nouveaux onglets du navigateur. [https://phabricator.wikimedia.org/T398361][https://phabricator.wikimedia.org/T298919][https://phabricator.wikimedia.org/T273526][https://phabricator.wikimedia.org/T286309] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:28|la tâche soumise|les {{formatnum:28}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:28||s}} la semaine dernière]]. Par exemple, le problème selon lequel les blocs globaux ne disposaient pas de l'option permettant de désactiver l'envoi d'e-mails a maintenant été résolu et sera disponible à l'utilisation à partir de la semaine du 13 janvier. [https://phabricator.wikimedia.org/T401293] '''Actualités pour la contribution technique''' * L'[[mw:Special:MyLanguage/VisualEditor/Citation tool|outil de citation VisualEditor]] et les [[mw:Special:MyLanguage/Help:Reference Previews|Aperçus de référence]] prennent désormais en charge "carte" comme type de référence. [https://phabricator.wikimedia.org/T411083] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.10|MediaWiki]]/[[mw:MediaWiki 1.46/wmf.11|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/03|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W03"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 12 janvier 2026 à 20:33 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29907192 --> == Thank You for Last Year – Join Wiki Loves Ramadan 2026 == Dear Wikimedia communities, We hope you are doing well, and we wish you a happy New Year. ''Last year, we captured light. This year, we’ll capture legacy.'' In 2025, communities around the world shared the glow of Ramadan nights and the warmth of collective iftars. In 2026, ''Wiki Loves Ramadan'' is expanding, bringing more stories, more cultures, and deeper global connections across Wikimedia projects. We invite you to explore the ''Wiki Loves Ramadan 2026'' [[m:Special:MyLanguage/Wiki Loves Ramadan 2026|Meta page]] to learn how you can participate and [[m:Special:MyLanguage/Wiki Loves Ramadan 2026/Participating communities|sign up]] your community. 📷 ''Photo campaign on '' [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan 2026|Wikimedia Commons]] If you have questions about the project, please refer to the FAQs: * [[m:Special:MyLanguage/Wiki Loves Ramadan/FAQ/|Meta-Wiki]] * [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan/FAQ|Wikimedia Commons]] ''Early registration for updates is now open via the '''[[m:Special:RegisterForEvent/2710|Event page]]''''' ''Stay connected and receive updates:'' * [https://t.me/WikiLovesRamadan Telegram channel] * [https://lists.wikimedia.org/postorius/lists/wikilovesramadan.lists.wikimedia.org/ Mailing list] We look forward to collaborating with you and your community. '''The Wiki Loves Ramadan 2026 Organizing Team''' 16 janvier 2026 à 20:44 (CET) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29879549 --> == <span lang="en" dir="ltr">Tech News: 2026-04</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W04"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/04|Translations]] are available. '''Updates for editors''' * The tray shown on [[Special:Diff|Special:Diff]] in mobile view has been redesigned. It is now collapsed by default, and incorporates a link to undo the edit being viewed, making it easier for mobile editors and reviewers to take action while keeping the interface uncluttered. [https://phabricator.wikimedia.org/T402297] * [[m:Special:GlobalWatchlist|The Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continues to improve — it now automatically determines the text direction (ensuring correct display of sites with unusual domain names) and shows detailed descriptions for log actions. Later this week, a new permanent link for page creations and CSS classes for each entry element will be added. [https://phabricator.wikimedia.org/T412505][https://phabricator.wikimedia.org/T287929][https://phabricator.wikimedia.org/T262768][https://phabricator.wikimedia.org/T414135] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:32}} community-submitted {{PLURAL:32|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the previously observed issue in Vector 2022, where anchor link targets were obscured by the sticky header, has now been addressed. [https://phabricator.wikimedia.org/T406114] '''Updates for technical contributors''' * As mentioned in the [[m:Special:MyLanguage/Tech/News/2025/44|October 2025 deprecation announcement]], MediaWiki Interfaces team will begin sunsetting all transform endpoints containing a trailing slash from the MediaWiki REST API the week of January 26. Changes are expected to roll out to all wikis on or before January 30th. All API users currently calling them are encouraged to transition to the non-trailing slash versions. Both endpoint variations can be found, compared, and tested using the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox]. If you have questions or encounter any problems, please file a ticket in Phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * Interactive reference documentation for the [[mw:Special:MyLanguage/Wikimedia REST API|Wikimedia REST API]] has moved. Requests to API docs previously hosted through [[mw:Special:MyLanguage/RESTBase|RESTBase]] (e.g.: <code dir=ltr>https://en.wikipedia.org/api/rest_v1/</code>) are now redirected to the [[w:en:Special:RestSandbox|REST Sandbox]]. * The [[mw:Special:MyLanguage/Wikidata Platform|WMF Wikidata Platform team]] (WDP) has published its [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|January 2026 newsletter]]. It includes updates on the legacy full-graph endpoint decommissioning, the User-Agent policy change, the monthly Blazegraph migration office hours, and efforts to reduce regressions caused by the legacy endpoint shutdown. As a reminder, you can [[m:Special:MyLanguage/Global message delivery/Targets/WDP team updates|subscribe to the WDP newsletter]]! * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.12|MediaWiki]] '''Meetings and events''' * The [[mw:Wikimedia Hackathon Northwestern Europe 2026|Wikimedia Hackathon Northwestern Europe 2026]] will take place on 13-14 March 2026 in Arnhem, the Netherlands. Applications opened mid-December and will close soon or when capacity is reached. It's a two-day, technically oriented hackathon bringing together Wikimedians from the region. Hope to see you there! '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/04|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W04"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 19 janvier 2026 à 21:29 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29943403 --> == Révision annuelle du code universel de conduite et des lignes directrices de l'application == <section begin="announcement-content" /> Nous vous informons que la période de relecture annuelle du Code de conduite universel et des règles d'applications est actuellement ouverte. Vous pouvez faire vos commentaires sur les modifications que vous souhaitez apporter jusqu'au 9 février 2026. C'est la première d'une série d'étapes nécessaires pour la révision annuelle. Vous trouverez [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|d'autres informations et les discussions auxquelles participer sur la page UCoC de Meta]]. Le [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Comité de coordination du code universel de conduite]] (U4C &mdash; Universal Code of Conduct Coordinating Committee) est un groupe global dont le rôle est de fournir une implémentation équitable et cohérente de l'UCoC. Cette relecture annuelle a été envisagée et mise en place par l'U4C. Pour plus d'informations et les responsabilités de l'U4C, veuillez lire la [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|Charte de l'U4C]]. Veuillez partager ces informations avec les autres membres concernés de votre communauté. -- En coopération avec l'U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|discussion]])<section end="announcement-content" /> 19 janvier 2026 à 22:01 (CET) <!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == Actualités techniques n° 2026-05 == <section begin="technews-2026-W05"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/05|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * La Fondation Wikimedia invite à donner des commentaires sur [[m:Special:MyLanguage/Product and Technology Advisory Council/Year1 Reflections and Proposed Way Forward 2026 Update|l’avenir proposé]] du [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif des produits et technologies]] jusqu’au 28 février. * Tous les utilisateurs disposant d'un compte enregistré peuvent désormais utiliser des clés d'accès pour la [[m:Special:MyLanguage/Help:Two-factor authentication|double authentification]] (2FA). Les clés d'accès sont un moyen simple de se connecter sans utiliser un second appareil. Elles vérifient l'identité de l'utilisateur à l'aide d'une empreinte digitale, d'une reconnaissance faciale ou d'un code PIN. Pour configurer une clé d'accès, configurez d'abord une méthode 2FA classique. Actuellement, pour se connecter avec une clé d'accès, les utilisateurs doivent également utiliser un mot de passe. Plus tard ce trimestre, la connexion sans mot de passe permettra aux utilisateurs de se connecter d'un simple clic avec une clé d'accès. Les utilisateurs disposant de droits avancés devront également avoir la 2FA activée. Cela fait partie du projet [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security|Sécurité du compte]]. * Les contributeurs non enregistrés sur des IP bloquées ou des plages d'IP bloquées peuvent désormais interagir sur le wiki pour faire appel d'un blocage en créant un compte temporaire afin de contester un blocage sur la page de discussion de l'utilisateur, sauf si l'option « empêcher cet utilisateur de modifier sa propre page de discussion » est activée. Cela résout le problème des utilisateurs déconnectés incapables d'utiliser le processus de déblocage par défaut via la page de discussion de l'utilisateur. [https://phabricator.wikimedia.org/T398673] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:20|la tâche soumise|les {{formatnum:20}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:20||s}} la semaine dernière]]. Par exemple, la description des méthodes d'authentification à deux facteurs (2FA) sur la page de gestion a été mise à jour. Il est désormais plus clair et plus facile pour les utilisateurs à comprendre et à utiliser. [https://phabricator.wikimedia.org/T332385] '''Actualités pour la contribution technique''' * Une nouvelle variable AbuseFilter, <code>account_type</code>, a été ajoutée pour fournir un moyen fiable de déterminer le type de compte créé dans les actions <code>createaccount</code> et <code>autocreateaccount</code>. Dans le cadre de ce changement, la variable <code>accountname</code> a été renommée en <code>account_name</code>, et <code>accountname</code> est désormais obsolète. Les gestionnaires de filtres doivent mettre à jour tous les filtres qui utilisent des vérifications de type de compte codées en dur ou la variable obsolète. [https://phabricator.wikimedia.org/T414049] * Les vignettes d'images demandées dans des tailles non standard, et en utilisant des méthodes non standard telles que les requêtes directes à <code dir=ltr><nowiki>upload.wikimedia.org/…</nowiki></code>, cesseront de fonctionner dans un proche avenir. Ce changement vise à prévenir les abus externes continus par des robots et des aspirateurs web. Certains utilisateurs ayant des CSS/JS personnalisés, les administrateurs d'interface qui peuvent corriger les gadgets et les thèmes locaux, ainsi que les auteurs d'outils, devront mettre à jour leur code pour utiliser des tailles de vignettes standard. [[phab:T414805|Des détails, des liens de recherche et des exemples de correction sont disponibles dans la tâche]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.13|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/05|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W05"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 26 janvier 2026 à 22:17 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29969530 --> == <span lang="en" dir="ltr">Tech News: 2026-06</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W06"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/06|Translations]] are available. '''Updates for editors''' * The "{{int:pageinfo-toolboxlink}}" feature, which gives validating information about a page ([{{fullurl:{{FULLPAGENAME}}|action=info}} example]), now automatically includes a table of contents. If there is a local [[{{ns:8}}:Pageinfo-header]] page created by individual users, it can now be removed. [https://phabricator.wikimedia.org/T363726] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, VisualEditor previously added bold or italic formatting inside link descriptions, making the wikicode complex. This has now been fixed. [https://phabricator.wikimedia.org/T409669] '''Updates for technical contributors''' * There was no XML dump on 20 January. Additionally, from now on, dumps will be generated once per month only. [https://phabricator.wikimedia.org/T414389] * The MediaWiki Interfaces team removed support for all transform endpoints containing a trailing slash from the [https://www.mediawiki.org/wiki/Special:MyLanguage/API:REST%20API MediaWiki REST API]. All API users currently calling those endpoints are encouraged to transition to the non-trailing slash versions. If you have questions or encounter any problems, please file a ticket in phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.14|MediaWiki]] '''Weekly highlight''' * Users are reminded that the Wikimedia Foundation has shared some guiding questions for the July 2026–June 2027 Annual Plan on [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] and ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. These focus on global trends, faster and healthier experimentation, better support for newcomers, strengthening editors and advanced users, improving collaboration across projects, and growing and retaining readership. Feedback and ideas are welcome on the [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|talk page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/06|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W06"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 février 2026 à 18:43 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30000986 --> == Actualités techniques n° 2026-07 == <section begin="technews-2026-W07"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/07|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] Les contributeurs connectés qui gèrent de grandes ou complexes listes de suivi peuvent désormais organiser et filtrer les pages surveillées de manière à améliorer leurs flux de travail grâce à la nouvelle fonctionnalité [[mw:Special:MyLanguage/Help:Watchlist labels|Étiquettes de liste de suivi]]. En ajoutant des étiquettes personnalisées (par exemple : pages que vous avez créées, pages surveillées pour vandalisme, ou pages de discussion), les utilisateurs peuvent identifier plus rapidement ce qui nécessite une attention, réduire la charge cognitive et répondre plus efficacement. Cela améliore l'utilisabilité de la liste de suivi, en particulier pour les éditeurs très actifs. * Une nouvelle fonctionnalité disponible sur [[Special:Contributions|Special:Contributions]] montre [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts|des comptes temporaires]] qui sont probablement utilisés par la même personne, et rend ainsi le patrouillage moins chronophage. En vérifiant les contributions d'un compte temporaire, les utilisateurs ayant accès aux adresses IP des comptes temporaires peuvent désormais avoir une vue des contributions des comptes temporaires associés. La fonctionnalité recherche toutes les adresses IP associées à un compte temporaire donné pendant la période de conservation des données et affiche toutes les contributions de tous les comptes temporaires ayant utilisé ces adresses IP. [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts#February 2026: Improvements to the patroller tooling|Plus...]] [https://phabricator.wikimedia.org/T415674] * Lorsque les éditeurs prévisualisent une modification de wikitexte, la boîte de rappel indiquant qu'ils ne voient qu'une prévisualisation (qui est affichée en haut) a désormais un fond gris/neutre au lieu d'un fond jaune/d'avertissement. Cela facilite la distinction entre les notes de prévisualisation et les avertissements réels (par exemple, les conflits de modification ou les cibles de redirection problématiques), qui seront désormais affichés dans des boîtes d'avertissement ou d'erreur séparées. [https://phabricator.wikimedia.org/T414742] * La [[m:Special:GlobalWatchlist|Liste de suivi globale]] vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page. L' [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continue de s'améliorer — elle prend désormais en charge correctement plus d'un site Wikibase, par exemple à la fois [[d:|Wikidata]] et [[testwikidata:|testwikidata]]. De plus, des problèmes concernant la direction du texte ont été résolus pour les utilisateurs qui préfèrent Wikidata ou d'autres sites Wikibase dans des langues de droite à gauche (RTL). [https://phabricator.wikimedia.org/T415440][https://phabricator.wikimedia.org/T415458] * <span lang="en" dir="ltr" class="mw-content-ltr">The automatic "magic links" for ISBN, RFC, and PMID numbers have been [[mw:Special:MyLanguage/Help:Magic links|deprecated in wikitext since 2021]] due to inflexibility and difficulties with localization. Several wikis have successfully replaced RFC and PMID magic links with equivalent external links, but a template was often required to replace the functionality of the ISBN magic link. There is now a new [[mw:Special:MyLanguage/Help:Magic words#isbn|built-in parser function]] <code dir=ltr><nowiki>{{#isbn}}</nowiki></code> available to replace the basic functionality of the ISBN magic link. This makes it easier for wikis who wish to migrate off of the deprecated magic link functionality to do so.</span> [https://phabricator.wikimedia.org/T145604] * Deux nouveaux wikis ont été créés : ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q35401|Jju]] ([[w:kaj:|<code>w:kaj:</code>]]) [https://phabricator.wikimedia.org/T413283] ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q1186896|Nawat]] ([[w:ppl:|<code>w:ppl:</code>]]) [https://phabricator.wikimedia.org/T413273] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * Un nouveau groupe d'utilisateurs global a été créé : [[{{int:grouppage-local-bot}}|{{int:group-local-bot}}]]. Il sera utilisé en interne par le logiciel pour permettre aux robots communautaires de contourner les limites de débit appliquées aux [[w:en:Web_scraping|web scrapers]] abusifs. Les comptes approuvés en tant que robots sur au moins un wiki Wikimedia seront automatiquement ajoutés à ce groupe. Cela ne changera pas les autorisations dont dispose le robot. [https://phabricator.wikimedia.org/T415588] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.15|MediaWiki]] '''Rencontres et évènements''' * La [[mw:Special:MyLanguage/MediaWiki Users and Developers Conference Spring 2026|Conférence des utilisateurs et des développeurs de MediaWiki, Printemps 2026]] se tiendra du 25 au 27 mars à Salt Lake City, États-Unis. Cet événement est organisé par et pour la communauté MediaWiki de tiers. Vous pouvez proposer des sessions et vous inscrire pour y assister. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/AZBWVI46SDEB65PGR5J6E4TYOQQEZXM7/] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/07|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W07"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10 février 2026 à 00:30 (CET) <!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30026671 --> == Actualités techniques n° 2026-08 == <section begin="technews-2026-W08"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/08|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * <span class="mw-translate-fuzzy">L'[[mw:Special:MyLanguage/Wikimedia Site Reliability Engineering|équipe SRE]] va procéder au nettoyage d'[[m:Special:MyLanguage/Etherpad|Etherpad]], l'éditeur web open source de documents collaboratifs en temps réel. Tous les blocs-notes seront définitivement supprimés après le 30 avril 2026 – si des projets de migration sont encore en cours à cette date, l'équipe pourra réexaminer la date au cas par cas. Veuillez effectuer des sauvegardes locales de tout contenu que vous souhaitez conserver, car les données supprimées ne pourront pas être récupérées. Ce nettoyage permet de réduire la taille de la base de données et l'empreinte de l'infrastructure. Etherpad continuera de prendre en charge la collaboration en temps réel, mais le stockage à long terme n'est plus assuré. D'autres nettoyages pourront avoir lieu ultérieurement sans préavis.</span> [https://phabricator.wikimedia.org/T415237] '''Actualités pour la contribution''' * L'équipe de Recherche d'Informations lancera une [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|expérimentation sur l'application mobile Android]], afin de tester des fonctionnalités de recherche hybrides capables de gérer à la fois les requêtes sémantiques et par mots-clés. L'amélioration de la recherche sur la plateforme permettra aux lecteurs de trouver plus facilement ce qu'ils cherchent, directement sur Wikipédia. L'expérimentation sera d'abord lancée sur Wikipédia en grec fin février, puis sur les versions anglaise, française et portugaise en mars. [https://diff.wikimedia.org/2026/01/08/semantic-search-making-it-easier-to-find-the-information-readers-want/ En savoir plus] sur le blog ''Diff''. [https://www.mediawiki.org/wiki/Readers/Information_Retrieval] * L'équipe « Croissance des lecteurs » mènera [[mw:Special:MyLanguage/Readers/Reader Growth/WE3.10.2 Mobile Table of Contents|une expérience]] auprès des utilisateurs de la version mobile du site web qui ajoute une table des matières et développe automatiquement toutes les sections des articles, afin de mieux comprendre les problèmes de navigation qu'ils rencontrent. Le test sera disponible sur les versions arabe, chinoise, anglaise, française, indonésienne et vietnamienne de Wikipedia. * Auparavant, les notifications ([[{{ns:8}}:Sitenotice]] et [[{{ns:8}}:Anonnotice]]) du site ne s'affichaient que sur la version ordinateur. Maintenant, elles s'afficheront désormais sur toutes les plateformes. Les utilisateurs mobiles verront ces notifications. Les administrateurs du site doivent être prêts à tester et à corriger les notifications sur les appareils mobiles afin d'éviter toute interférence avec les articles. Pour désactiver ces notifications, les administrateurs d'interface peuvent ajouter <code dir="ltr">#siteNotice { display: none; }</code> à [[{{ns:8}}:Minerva.css]]. [https://phabricator.wikimedia.org/T138572][https://phabricator.wikimedia.org/T416644] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:19|la tâche soumise|les {{formatnum:19}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:19||s}} la semaine dernière]]. Par exemple, un problème concernant la section ''[[Special:RecentChanges|Spécial:Modifications récentes]]'' a été résolu. Auparavant, cliquer sur « Masquer » dans les filtres actifs entraînait la disparition du bouton « Afficher les nouvelles modifications depuis… », alors qu'il aurait dû rester visible. Ce bouton fonctionne désormais correctement. [https://phabricator.wikimedia.org/T406339] '''Actualités pour la contribution technique''' * Une nouvelle documentation est désormais disponible pour aider les rédacteurs à déboguer les fonctionnalités de recherche interne. Elle facilite le dépannage lorsque des pages n'apparaissent pas dans les résultats, lorsque le classement semble inattendu et lorsqu'il est nécessaire d'inspecter le contenu indexé, ce qui permet de mieux comprendre et d'analyser le comportement de la recherche. [[mw:Help:CirrusSearch/Debug|En savoir plus]]. [https://phabricator.wikimedia.org/T411169] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.16|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/08|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W08"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 février 2026 à 20:17 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30086330 --> == <span lang="en" dir="ltr">Tech News: 2026-09</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W09"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/09|Translations]] are available. '''Weekly highlight''' * [[mw:Special:MyLanguage/Edit check/Reference Check|Reference Check]] has been deployed to English Wikipedia, completing its rollout across all Wikipedias. The feature prompts newcomers to add a citation before publishing new content, helping reduce common citation-related reverts and improve verifiability. In A/B testing, the impact was substantial: newcomers shown Reference Check were approximately 2.2 times more likely to include a reference on desktop and about 17.5 times more likely on mobile web. [https://analytics.wikimedia.org/published/reports/editing/reference_check_ab_test_report_final_2025.html] '''Updates for editors''' * The [[mw:Special:MyLanguage/Extension:InterwikiSorting|InterwikiSorting extension]], which allowed for the [[m:Special:MyLanguage/Interwiki sorting order|sorting of interwiki links]], has been undeployed from Wikipedia. As a result, editors who had enabled interwiki link sorting in non-compact mode (full list format) will now see links reordered. The links moving forward will be listed in the alphabetical order of language code. [https://phabricator.wikimedia.org/T253764] * Later this week, people who are editing a page-section using the mobile visual editor, will notice a new "Edit full page" button. When tapped, you will be able to edit the entire article. This helps when the change you want to make is outside the section you initially opened. [https://phabricator.wikimedia.org/T387175][https://phabricator.wikimedia.org/T409112] * [[mw:Special:MyLanguage/Readers/Reader Experience|The Reader Experience team]] is inviting editors to assess whether dark mode should still be considered "beta" on their wiki, based on their experience of how well it functions on desktop and mobile. If the feature is deemed mature, editors can update the interface messages in <code dir=ltr>MediaWiki:skin-theme-description</code> and <code dir=ltr>MediaWiki:Vector-night-mode-beta-tag</code> to indicate that dark mode is ready and no longer considered beta. * The improved [[mw:Wikimedia_Apps/Team/iOS/Activity_Tab|Activity tab]] which displays user-insights is now available to all users of the Wikipedia iOS app (version 7.9.0 and later). Following earlier A/B testing that showed higher account creation among users with access to the feature, it has been rolled out to 100% of users along with some updates. The Activity tab now shows your edited articles in the timeline, offers editing impact insights like contribution counts and article view trends, and customization options to improve in-app experience for users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, a bug that prevented [[mw:Special:MyLanguage/Extension:DiscussionTools|DiscussionTools]] from working on mobile has now been fixed, restoring full functionality. [https://phabricator.wikimedia.org/T415303] '''Updates for technical contributors''' * The [[m:Special:GlobalWatchlist|Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] that makes this possible continues to improve. The latest upgrade is the inclusion of a [[mw:Extension:GlobalWatchlist#hook|new hook]], <code dir=ltr>ext.globalwatchlist.rebuild</code>, which fires after each watchlist rebuild. This allows you to run gadgets and user scripts for the Special page. [https://phabricator.wikimedia.org/T275159] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.17|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/09|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W09"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 février 2026 à 20:03 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30119102 --> == Actualités techniques n° 2026-10 == <section begin="technews-2026-W10"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/10|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments|mode Anniversaire]] Wikipedia 25 est maintenant disponible sur Wikipédia en français, anglais, betawi, breton, chinois, espagnol, gorontalo, indonésien, italien, luxembourgeois, madurais, néerlandais, sicilien, tchèque, thaï et vietnamien ! Cette campagne à temps limitée célèbre 25 ans de Wikipédia avec une mascotte : « Baby Globe », disponible sous la forme d'un réglage. Lorsque ce réglage est activé, Baby Globe est montrée sur [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments/article configuration|environ 2 500 articles]], attendant d'être découverte par des lecteurs. Chaque communauté peut choisir d'activer le mode Anniversaire par consensus et en demandant à un administrateur de le rendre disponible et de le personaliser via une [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments#Community Configuration Demo|configuration]] sur le wiki local. '''Actualités pour la contribution''' * Le [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-référencement]], une nouvelle fonctionalité pour réutiliser des références avec des détails différents est maintenant disponible sur Wikipédia en suédois, polonais et [[:phab:T418209|quelques autres]]. Vous pouvez [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#test|essayer la fonctionalité]] sur ces projets ou sur testwiki et [https://en.wikipedia.beta.wmcloud.org/wiki/Sub-referencing betawiki]. Les retours des premiers essais sur Wikipédia en allemand ont été [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing/Learnings|publiés dans un rapport]]. Contactez l'équipe de Wikimédia Allemagne si vous êtes [[:m:Talk:WMDE Technical Wishes/Sub-referencing#Pilot wikis|intéressés pour devenir un wiki pilote]]. * La [[mw:Special:MyLanguage/Help:Edit check#Paste check|vérification du collage clavier]] sera disponible sur tous les Wikipédias cette semaine. Cette fonctionalité avertit les nouveaux contributeurs qui collent du texte qu'ils n'ont probablement pas écrit de vérifier si laisser celui-ci risque de causer une violation du droit d'auteur. La vérification du collage clavier [[mw:Special:MyLanguage/Edit check/Tags|marque]] toutes les modifications où l'avertissement a été montré pour permettre leur vérification. Les administrateurs locaux peuvent configurer les différents aspects de cette fonctionalité à travers [[{{#special:EditChecks}}]]. Des [[mw:Special:MyLanguage/Edit check/Paste Check#A/B Experiment|études]] sur 22 wikis ont montré que cette vérification permet une réduction de 18% des annulations comparé au groupe de contrôle. Les traducteurs peuvent [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-visualeditor-ve-mw-editcheck&filter=&optional=1&action=translate aider à traduire] cette fonctionalité. * <span lang="en" dir="ltr" class="mw-content-ltr">The [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience team]] will be standardizing the user menu in the top right for all mobile users so that it is closer to the desktop experience. Currently this user menu is only visible to users with Advanced Mobile Controls (AMC) turned on. The only change is that a couple buttons previously in the left-side menu will move to the top right for users who do not have AMC turned on. This change is expected to go out March 9 and seeks to improve the user interface.</span> [https://phabricator.wikimedia.org/T413912] * À partir de la semaine du 2 mars, les emails envoyés lorsqu'une adresse email a été ajoutée, supprimée ou changée pour un compte changera pour adopter un formattage HTML beaucoup plus agréable et plus clair que le texte brut précédent. [https://phabricator.wikimedia.org/T410807] * Les notifications sont actuellement limitées à 2 000 entrées historiques par utilisateur et remontent à 2013 lorsque la fonctionnalité a été publiée. Le système va être modifié pour ne stocker que les notifications des 5 dernières années, mais jusqu'à 10 000 d'entre elles. Cela contribuera à la santé à long terme des infrastructures et à empêcher que les notifications plus récentes disparaissent trop tôt. [https://phabricator.wikimedia.org/T383948] * <span lang="en" dir="ltr" class="mw-content-ltr">The [[m:Special:GlobalWatchlist|Global Watchlist]] which lets you view your watchlists from multiple wikis on a single page continues to see improvements. The latest update improves label usage experience. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] now allows activating the [[mw:Special:MyLanguage/Manual:Language#Fallback languages|language fallback system]] for Wikidata items without labels in the viewed language, and showing those labels in the user’s preferred Wikidata language if no <code dir=ltr>uselang=</code> URL parameter is provided.</span> [https://phabricator.wikimedia.org/T373686][https://phabricator.wikimedia.org/T416111] * L'équipe Wikipédia Android a commencé un test beta de la [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|recherche hybride]] sur Wikipédia en grec. Cette recherche hybride supporte les requêtes sémantique et par mot clés, permettant aux utilisateurs de trouver ce qu'ils cherchent plus facilement. * Pour des raisons de sécurité, les membres de certains groupes sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir la double authentification]] (A2F) d'activée. Actuellement, l'A2F n'est nécessaire que pour utiliser les droits du groupe, et non pour en faire partie. Vu que ce système admet certaines failles, il sera [[phab:T418580|changé graduellement en mars]]. Les membres de ces groupes ne pourront plus désactiver la dernière méthose d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Il sera toujours possible de rajouter d'autres méthodes d'authentification et d'en enlever, tant qu'une est toujours activée. Dans la seconde moitié de mars, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique aux administrateurs CentralNotice, aux vérificateurs d'utilisateurs, aux administrateurs d'interface, aux masqueurs, aux staff de Wikidata et Wikifonctions ainsi qu'aux bureaux IT et Confiance et sécurité de la WMF. Rien ne changera pour les autres utilisateurs. Voir la tâche liée pour le calendrier de déploiement. [https://phabricator.wikimedia.org/T418580] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, le problème empêchant les utilisateurs de créer une instance dans [https://www.wikibase.cloud/ Wikibase.cloud] a maintenant été résolu. [https://phabricator.wikimedia.org/T416807] '''Actualités pour la contribution technique''' * <span lang="en" dir="ltr" class="mw-content-ltr">To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], over the next month the Wikimedia Foundation will implement global API rate limits across our APIs. In early March, stricter limits will be applied to unidentified requests from outside Toolforge/WMCS and API requests that are made from web browsers. In April, higher limits will be applied to identified traffic. These limits are intentionally set as high as possible to minimise impact on the community. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]].</span> * <span lang="en" dir="ltr" class="mw-content-ltr">The Wikidata Query Service Linked Data Fragment (LDF) endpoint will be decommissioned in February. This endpoint served limited traffic, which was successfully migrated to other data access methods that were better suited to support existing use cases. The hardware used to support the LDF endpoint will be reallocated to support the ongoing backend migration efforts.</span> [https://phabricator.wikimedia.org/T415696] * Le nouvel analyseur syntaxique Parsoid [[mw:Special:MyLanguage/Parsoid/Parser Unification/Updates|continue d'être déployés sur plus de wikis]], améliorant la pérennité de la platforme et rendant plus facile l'ajout de nouvelles fonctionalités de lecture et de modification. Parsoid est maintenant l'analyseur par défaut sur 488 wikis de la WMF (268 Wikipédias), couvrant plus de 10% de toutes les lectures de pages Wikipédia. * Le processus et les critères pour [[Special:MyLanguage/Wikimedia Enterprise#Access|demander un accès exceptionnel]] au flux à fort volume de l'API ''Wikimédia Entreprise'' (sans coût pour des utilisations en rapport à notre mission) [[m:Talk:Wikimedia Enterprise#Exceptional access criteria|ont maintenant été publiés]]. Notre but est de donner une documentation plus claire et plus complète aux utilisateurs. * [https://techblog.wikimedia.org/ Le blog Tech], dédié à la communité technique de Wikimédia [https://techblog.wikimedia.org/2026/02/24/a-tech-blog-diff/ va migrer] vers [[diffblog:|Diff]], le blog pour les nouvelles et événements de la communauté. La migration devrait être terminée en Avril 2026, après quoi les nouveaux posts seront acceptés pour être publiés. Les lecteurs pourront lire les posts - anciens ou nouveaux - sur https://diff.wikimedia.org/. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.18|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/10|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W10"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 mars 2026 à 18:51 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30137798 --> == <span lang="en" dir="ltr">Tech News: 2026-11</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W11"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/11|Translations]] are available. '''Weekly highlight''' * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. * Last week, all wikis had 2 hours of read-only time, and extended unavailability for user-scripts and gadgets. This was due to a security incident which has since been resolved. Work is ongoing to prevent re-occurrences. For current information please see the [[m:Steward's noticeboard#Statement on Meta about today's user script security incident|post on the Stewards' noticeboard]] ([[m:Special:MyLanguage/Wikimedia Foundation/Product and Technology/Product Safety and Integrity/March 2026 User Script Incident|translations]]). '''Updates for editors''' * Users facing multiple blocks on mobile will now see the reasons for each block separately, instead of a generic message. This helps them understand why they are blocked and what steps they can take to resolve the issue. For example, users affected for using common VPNs (such as [[Special:MyLanguage/Apple iCloud Private Relay|iCloud Private Relay]]) will receive clearer guidance on what they need to do to start editing again. [https://phabricator.wikimedia.org/T357118] * Later this week, [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Suggestion Mode]] will become available as a beta feature within the visual editor at all Wikipedias. This feature proactively suggests various types of actions that people can consider taking to improve Wikipedia articles, and learn about related guidelines. The feature is locally configurable, and can also be locally expanded with custom Suggestions. Current settings can be seen at [[Special:EditChecks]] and there are [[mw:Special:MyLanguage/Help:Suggestion mode#For administrators %E2%80%93 local customization|instructions for how administrators can customize]] the links to point to local guidelines. The feature is connected to [[mw:Special:MyLanguage/Help:Edit check|Edit check]] which suggests improvements while someone is writing new content. In the future, the Editing team plans to evaluate the feature's impact with newcomers through a controlled experiment. [https://phabricator.wikimedia.org/T404600] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:23}} community-submitted {{PLURAL:23|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the issue where the cursor became misaligned during the use of CodeMirror’s syntax highlighting, which makes wikitext and code easier to read, has now been fixed. This problem specifically affected users who defined a font rule in a custom stylesheet while creating a new topic with DiscussionTools. [https://phabricator.wikimedia.org/T418793] '''Updates for technical contributors''' * API rate limiting update: To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], global API rate limits will be applied this week to requests without a compliant User-Agent that originate from outside Toolforge/WMCS and to unauthenticated requests made from web browsers. Higher limits will be applied to identified traffic in April. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]]. * The new GraphQL API has been released. The API was developed as a flexible alternative to select features of the Wikidata Query Service (WDQS), to improve developer experience and foster adaptability, and efficient data access. Try it out and [[d:Wikidata:Wikibase GraphQL#Feedback and development|give feedback]]. You can also [https://greatquestion.co/wikimediadeutschland/GraphQLAPI/apply sign up for usability tests]. * The [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group|PTAC Unsupported Tools Working Group]] continued improvements to [[commons:Special:MyLanguage/Commons:Video2commons#|Video2Commons]] in February, with fixes addressing authentication errors, large-file handling, task queue visibility, and clearer upload behavior. Work is still ongoing in some areas, including changes related to deprecated server-side uploads. Read [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group#February 2026|this update]] to learn more. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.19|MediaWiki]] '''In depth''' * The Article Guidance team invites experienced Wikipedia editors from selected [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators#Collaborators|pilot wikis]] and interested contributors from other Wikipedias to fill out this questionnaire which is available in [https://docs.google.com/forms/d/e/1FAIpQLSfmLeVWnxmsCbPoI_UF2jyRcn73WRGWCVPHzerXb4Cz97X_Ag/viewform English], [https://docs.google.com/forms/d/e/1FAIpQLSd6rzr4XXQw8r4024fE3geTPFe13M_6w7Mitj-YJi0sOlWTAw/viewform?usp=header Arabic], [https://docs.google.com/forms/d/e/1FAIpQLSdok3-RfB18lcugYTUMGkpwmqG_8p760Wv4dCXitOXOszjUDw/viewform?usp=header Bengali], [https://docs.google.com/forms/d/e/1FAIpQLSfjTfYp4jEo0akA4B1e-Nfg3QZPCudUjhJzHzzDi6AHyAaMGA/viewform?usp=header Japanese], [https://docs.google.com/forms/d/e/1FAIpQLScteVoI29Aue4xc72dekk-6RYtvmMgQxzMI900UOawrFrSTWg/viewform?usp=header Portuguese], [https://docs.google.com/forms/d/e/1FAIpQLSetdxnYwL3ub2vqA7awCg5hJZPMIYcDPaiTe12rY9h0GYnVlw/viewform?usp=header Persian], and [https://docs.google.com/forms/d/e/1FAIpQLScNvfJF-Ot-4pzA4qAN771_0QDJ4Li19YcUsaTgSKW8Nc7U_Q/viewform?usp=header Turkish]. Your answers will help the team customize guidance for less experienced editors and help them learn community policies and practices while creating an article. Learn more [[mw:Special:MyLanguage/Article guidance|on the project page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/11|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W11"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 9 mars 2026 à 19:52 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30213008 --> == <span lang="en" dir="ltr">Tech News: 2026-12</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W12"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/12|Translations]] are available. '''Updates for editors''' * The [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature, also known as [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], has been used for wikitext syntax highlighting since November 2024. It will be promoted out of beta by May 2026 in order to bring improvements and new [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Features|features]] to all editors who use the standard syntax highlighter. If you have any questions or concerns about promoting the feature out of beta, [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|please share]]. [https://phabricator.wikimedia.org/T259059] * Some changes to local user groups are performed by stewards on Meta-Wiki and logged there only. Now, interwiki rights changes will be logged both on Meta-Wiki and the wiki of the target user to make it easier to access a full record of user's rights changes on a local wiki. Past log entries for such changes will be backfilled in the coming weeks. [https://phabricator.wikimedia.org/T6055] * On wikis using [[m:Special:MyLanguage/Flagged Revisions|Flagged Revisions]], the number of pending changes shown on [[{{#Special:PendingChanges}}]] previously counted pages which were no longer pending review, because they have been removed from the system without being reviewed, e.g. due to being deleted, moved to a different namespace, or due to wiki configuration changes. The count will be correct now. On some wikis the number shown will be much smaller than before. There should be no change to the list of pages itself. [https://phabricator.wikimedia.org/T413016] * Wikifunctions composition language has been rewritten, resulting in a new version of the language. This change aims to increase service stability by reducing the orchestrator's memory consumption. This rewrite also enables substantial latency reduction, code simplification, and better abstractions, which will open the door to later feature additions. Read more about [[f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-11|the changes]]. * Users can now sort search results alphabetically by page title. The update gives an additional option to finding pages more easily and quickly. Previously, results could be sorted by Edit date, Creation date, or Relevance. To use the new option, open 'Advanced Search' on the search results page and select 'Alphabetically' under 'Sorting Order'. [https://phabricator.wikimedia.org/T403775] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:28}} community-submitted {{PLURAL:28|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented UploadWizard on Wikimedia Commons from importing files from Flickr has now been fixed. [https://phabricator.wikimedia.org/T419263] '''Updates for technical contributors''' * A new special page, [[{{#special:LintTemplateErrors}}]], has been created to list transcluded pages that are flagged as containing lint errors to help users discover them easily. The list is sorted by the number of transclusions with errors. For example: [[{{#special:LintTemplateErrors}}/night-mode-unaware-background-color]]. [https://phabricator.wikimedia.org/T170874] * Users of the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature have been using [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] for syntax highlighting when editing JavaScript, CSS, JSON, Vue and Lua content pages, for some time now. Along with promoting CodeMirror 6 out of beta, the plan is to replace CodeEditor as the standard editor for these content models by May 2026. [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|Feedback or concerns are welcome]]. [https://phabricator.wikimedia.org/T419332] * The [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] JavaScript modules will soon be upgraded to CodeMirror 6. Leading up to the upgrade, loading the <code dir=ltr>ext.CodeMirror</code> or <code dir=ltr>ext.CodeMirror.lib</code> modules from gadgets and user scripts was deprecated in July 2025. The use of the <code dir=ltr>ext.CodeMirror.switch</code> hook was also deprecated in March 2025. Contributors can now make their scripts or gadgets compatible with CodeMirror 6. See the [[mw:Special:MyLanguage/Extension:CodeMirror#Gadgets and user scripts|migration guide]] for more information. [https://phabricator.wikimedia.org/T373720] * The MediaWiki Interfaces team is expanding coverage of REST API module definitions to include [[mw:Special:MyLanguage/API:REST API/Extensions|extension APIs]]. REST API modules are groups of related endpoints that can be independently managed and versioned. Modules now exist for [https://phabricator.wikimedia.org/T414470 GrowthExperiments] and [https://phabricator.wikimedia.org/T419053 Wikifunctions] APIs. As we migrate extension APIs to this structure, documentation will move out of the main MediaWiki OpenAPI spec and REST Sandbox view, and will instead be accessible via module-specific options in the dropdown on the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox] (i.e., [[{{#Special:RestSandbox}}]], available on all wiki projects). * The [[mw:Special:MyLanguage/Extension:Scribunto|Scribunto]] extension provides different pieces of information about the wiki where the module is being used via the [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual|mw.site]] library. Starting last week, the library also provides a [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#mw.site.wikiId|way]] of accessing the [[mw:Special:MyLanguage/Manual:Wiki ID|wiki ID]] that can be used to facilitate cross-wiki module maintenance. [https://phabricator.wikimedia.org/T146616] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.20|MediaWiki]] '''In depth''' * The [[m:Special:MyLanguage/Coolest Tool Award|2026 Coolest Tool Award]] celebrating outstanding community tools, is now open for nominations! Nominate your favorite tool using the [https://wikimediafoundation.limesurvey.net/435684?lang=en nomination survey] form by 23 March 2026. For more information on privacy and data handling, please see the [[foundation:Special:MyLanguage/Legal:Coolest_Tool_Award_2026_Survey_Privacy_Statement|survey privacy statement]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/12|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W12"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 mars 2026 à 20:35 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30260505 --> == <span lang="en" dir="ltr">Upcoming deployment of CampaignEvents extension to Wikibooks</span> == <div lang="en" dir="ltr"> <section begin="message"/> Hello everyone, We are writing to inform you that the [[mw:Help:Extension:CampaignEvents|CampaignEvents extension]] will be deployed to all Wikibooks projects during the week of '''23 March 2026'''. This follows last year’s broader rollout across Wikimedia projects. We realized that Wikibooks was not included at the time, and we’re now addressing that to ensure consistency across all communities. The CampaignEvents extension provides tools to support event and campaign organization on-wiki, including features like on-wiki event registration and collaboration lists(global event list). We welcome any questions, feedback, or concerns you may have. We are also happy to support anyone interested in trying out the tools. ''Apologies if this message is not in your preferred language. If you’re able to help translate it for your community, please feel free to do so.'' <section end="message"/> </div> <bdi lang="en" dir="ltr">[[User:Udehb-WMF|Udehb-WMF]] ([[User talk:Udehb-WMF|discussion]]) 19 mars 2026 à 19:22 (CET)</bdi> <!-- Message envoyé par User:Udehb-WMF@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=User:Udehb-WMF/sandbox/MM_target&oldid=30284073 --> == <span lang="en" dir="ltr">Tech News: 2026-13</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W13"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/13|Translations]] are available. '''Weekly highlight''' * Wikimedia site users can now log in without a password using passkeys. This is a secure method supported by fingerprint, facial recognition, or PIN. With this change, all users who opt for passwordless login will find it easier, faster, and more secure to log in to their accounts using any device. The new passkey login option currently appears as an autofill suggestion in the username field. An additional [[phab:T417120|"Log in with passkey" button]] will soon be available for users who have already registered a passkey. This update will improve security and user experience. The [[c:File:Passwordless_login_screencast.webm|screen recording]] demonstrates the passwordless login process step by step. * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. '''Updates for editors''' * Wikimedia site users can now export their notifications older than 5 years using a [[toolforge:echo-chamber|new Toolforge tool]]. This will ensure that users retain their important notifications and avoid them being lost based on the planned change to delete notifications older than 5 years, as previously announced. [https://phabricator.wikimedia.org/T383948] * Wikipedia editors in Indonesian, Thai, Turkish, and Simple English now have access to Special:PersonalDashboard. This is an [[mw:Special:MyLanguage/Moderator Tools/Dashboard|early version of an experience]] that introduces newer editors to patrolling workflows, making it easier for them to move from making edits to participating in more advanced moderation work on their project. [https://phabricator.wikimedia.org/T402647] * The [[Special:Block]] now has two minor interface changes. Administrators can now easily perform indefinite blocks through a dedicated radio button in the expiry section. Also, choosing an indefinite expiry provides a different set of common reasons to select from, which can be changed at: [[MediaWiki:Ipbreason-indef-dropdown]]. [https://phabricator.wikimedia.org/T401823] * Mobile editors [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#Logged-out|at several wikis]] can now see an improved logged-out edit warning, thanks to the recent updates from the Growth team. These changes released last week are part of ongoing efforts and tests to enhance [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|account creation experience on mobile]] and then increase participation. [https://phabricator.wikimedia.org/T408484] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:36}} community-submitted {{PLURAL:36|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented mobile web users from seeing the block information when affected by multiple blocks has been fixed. They can now see messages of all the blocks currently affecting them when they access Wikipedia. '''Updates for technical contributors''' * Images built using Toolforge will soon get the upgraded buildpacks version, bringing support for newer language versions and other upstream improvements and fixes. If you use Toolforge Build Service, review the recent [https://lists.wikimedia.org/hyperkitty/list/cloud-announce@lists.wikimedia.org/thread/EMYTA32EV2V5SQ2JIEOD2CL66YFIZEKV/ cloud-announce email] and update your build configuration as necessary to ensure your tools are compatible. [https://wikitech.wikimedia.org/w/index.php?title=Help:Toolforge/Building_container_images&oldid=2392097#Buildpack_environment_upgrade_process][https://phabricator.wikimedia.org/T380127] * The [https://api.wikimedia.org/wiki/Main_Page API Portal] documentation wiki will shut down in June 2026. API keys created on the API Portal will continue to work normally. api.wikimedia.org endpoints will be deprecated gradually starting in July 2026. Documentation on the API Portal is moving to [[mw:Wikimedia APIs|mediawiki.org]]. Learn more on the [[wikitech:API Portal/Deprecation|project page]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.21|MediaWiki]] '''In depth''' * [[m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]] is considering improvements to [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names|automatically generated reference names in VisualEditor]]. Please check out the [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names#Proposed solutions|proposed solutions]] and participate in the [[m:Talk:WMDE Technical Wishes/References/VisualEditor automatic reference names#Request for comment|request for comment]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/13|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W13"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 mars 2026 à 17:51 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30268305 --> == Actualités techniques n° 2026-14 == <section begin="technews-2026-W14"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/14|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le version Beta de [[abstract:|Abstract Wikipedia]], un nouveau projet Wikimédia indépendant du langage, a été lancée la semaine dernière. Ce projet permet aux communautés de construire des articles Wikipédia dans leur langue natale, qui peuvent directement être lus par les autres utilisateurs et utilisatrices dans leur propre langage. Le wiki fonctionne grâce à des instructions de Wikifunctions et au contenu structuré issu de Wikidata. [[:f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-26|En savoir plus]]. '''Actualités pour la contribution''' * L'équipe Croissance mène un test A/B afin d'évaluer l'effet d'un message plus clair et plus convivial encourageant à la création de comptes sur les wikis. Actuellement, lorsqu'un utilisateur mobile non connecté lance la modification, un message d'avertissement s'affiche, pouvant paraître abrupt et décourageant. Il présente également la modification par compte temporaire comme option par défaut, au lieu d'inciter à la création d'un compte. Le test est mené sur dix Wikipédia, dont les versions en arabe, français, espagnol et allemand. [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#2. Improve logged-out warning message (T415160)|En savoir plus]]. * L'équipe des applications Wikimédia sollicite vos commentaires sur [[mw:Special:MyLanguage/Wikimedia Apps/Team/Future of Editing on the Mobile Apps|comment devrait fonctionner l'édition dans les applications mobiles Wikipédia]]. La discussion porte sur l'amélioration de l'accès aux outils d'édition lorsque les utilisateurs appuient sur « Modifier ». Cette initiative s'inscrit dans un effort plus large visant à offrir aux lecteurs intéressés par la contribution une expérience utilisateur plus intuitive. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:45|la tâche soumise|les {{formatnum:45}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:45||s}} la semaine dernière]]. Par exemple, un problème avec la récupération de citations à partir du site d'archive de journaux [https://www.newspapers.com Newspapers.com], qui ne fonctionnait plus en raison d'un blocage des requêtes [[mw:Special:MyLanguage/Citoid|Citoid]], a maintenant été résolu. [https://phabricator.wikimedia.org/T419903] '''Actualités pour la contribution technique''' * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.22|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/14|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W14"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 30 mars 2026 à 21:25 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30329462 --> == Action Required: Update templates/modules for electoral maps (Migrating from P1846 to P14226) == Hello everyone, This is a notice regarding an ongoing data migration on Wikidata that may affect your election-related templates and Lua modules (such as <code>Module:Itemgroup/list</code>). '''The Change:'''<br /> Currently, many templates pull electoral maps from Wikidata using the property [[:d:Property:P1846|P1846]], combined with the qualifier [[:d:Property:P180|P180]]: [[:d:Q19571328|Q19571328]]. We are migrating this data (across roughly 4,000 items) to a newly created, dedicated property: '''[[:d:Property:P14226|P14226]]'''. '''What You Need To Do:'''<br /> To ensure your templates and infoboxes do not break or lose their maps, please update your local code to fetch data from [[:d:Property:P14226|P14226]] instead of the old [[:d:Property:P1846|P1846]] + [[:d:Property:P180|P180]] structure. A [[m:Wikidata/Property Migration: P1846 to P14226/List|list of pages]] was generated using Wikimedia Global Search. '''Deadline:'''<br /> We are temporarily retaining the old data on [[:d:Property:P1846|P1846]] to allow for a smooth transition. However, to complete the data cleanup on Wikidata, the old [[:d:Property:P1846|P1846]] statements will be removed after '''May 1, 2026'''. Please update your modules and templates before this date to prevent any disruption to your wiki's election articles. Let us know if you have any questions or need assistance with the query logic. Thank you for your help! [[User:ZI Jony|ZI Jony]] using [[Utilisateur:MediaWiki message delivery|MediaWiki message delivery]] ([[Discussion utilisateur:MediaWiki message delivery|discussion]]) 3 avril 2026 à 19:11 (CEST) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29941252 --> == Actualités techniques n° 2026-15 == <section begin="technews-2026-W15"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/15|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * L’[[mw:Special:MyLanguage/Help:Extension:CampaignEvents|extension CampaignEvents]] comprend désormais une nouvelle fonctionnalité de définition d’objectifs de groupe, permettant aux organisateurs de définir et de suivre les objectifs de l’événement, tels que le nombre d’articles créés et de contributeurs participants en temps réel. De même, les participants peuvent travailler vers des cibles communes et voir leur impact collectif au fur et à mesure que l’événement se déroule. Cette fonctionnalité est désormais disponible sur tous les wikis Wikimedia. Pour en savoir plus, consultez [[mw:Special:MyLanguage/Help:Extension:CampaignEvents/Registration/Collaborative contributions#Goal setting|la documentation]]. * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] La nouvelle fonctionnalité d'[[mw:Special:MyLanguage/Help:Watchlist labels|étiquettes de liste de suivi]] (annoncée dans les [[m:Special:MyLanguage/Tech/News/2026/07|Actualités techniques 2026-07 ]]) est désormais disponible via l'ÉditeurVisuel, l'éditeur de code et l'«étoile de suivi»(ou le lien de suivi, pour les habillages qui n'ont pas d'icône d'étoile). Auparavant, il n'était possible d'attribuer des étiquettes que via [[Special:EditWatchlist|Modifier la liste de suivi]]. Dans ces trois emplacements, il s'agit d'un nouveau champ situé après le champ d'expiration. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. Par exemple, le problème où les pages de discussion sur mobile avec Parsoid sont inutilisables après les en-têtes de section vides, a maintenant été résolu. [https://phabricator.wikimedia.org/T419171] '''Actualités pour la contribution technique''' * La [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|fonctionnalité de sous-référencement]], qui permet aux contributeurs d'ajouter des détails à une référence existante sans la dupliquer, sera progressivement déployée sur [[phab:T414094|davantage de wikis]] plus tard cette année. Les wikis utilisant le gadget [[mw:Special:MyLanguage/Reference Tooltips|Reference Tooltips]] sont encouragés à mettre à jour leur version (généralement sur [[m:MediaWiki:Gadget-ReferenceTooltips.js|MediaWiki:Gadget-ReferenceTooltips.js]] comme indiqué [https://en.wikipedia.org/w/index.php?diff=1344408362 ici]) pour assurer la compatibilité. D'autres gadgets liés aux références pourraient également être affectés. [https://phabricator.wikimedia.org/T416304] * Toutes les éditions de Wikinews seront fermées et passeront en mode lecture seule le 4 mai 2026. Le contenu restera accessible, mais aucune nouvelle modification ni aucun nouvel article ne pourra être ajouté. Cette fermeture a été approuvée par le Conseil d'administration de la Fondation Wikimedia à la suite de discussions prolongées. [[m:Wikimedia Foundation Board noticeboard#Board of Trustees Approves Closure of Wikinews|En savoir plus]]. * L'[[:mw:Special:MyLanguage/API:Action API|API d'action]] a proposé plusieurs formats pour les résultats demandés. L'un d'entre eux, <bdi lang="zxx" dir="ltr"><code><nowiki>format=php</nowiki></code></bdi>, sera bientôt supprimé. Veuillez vous assurer que vos scripts ou robots utilisent le [[mw:Special:MyLanguage/API:Data formats#Output|format JSON]]. Cette suppression devrait affecter très peu de scripts et de robots. [https://phabricator.wikimedia.org/T118538] * La page [[Special:NamespaceInfo|Special:NamespaceInfo]] inclut désormais les alias d'espace de noms. Par exemple «WP» pour l'espace de noms ''Projet'' (''Wikipédia'') sur la Wikipédia en allemand. [https://phabricator.wikimedia.org/T381455] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.23|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/15|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W15"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 6 avril 2026 à 18:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30362761 --> == <span lang="en" dir="ltr">Tech News: 2026-16</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W16"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/16|Translations]] are available. '''Weekly highlight''' * Experienced editors are invited to [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Main_Page test] the [[mw:Special:MyLanguage/Article guidance|Article guidance]] feature, designed to help less-experienced editors create well-structured, policy-compliant Wikipedia articles. Testing instructions are [[mw:Special:MyLanguage/Article guidance/Test feature guide|available]]. Also, after reviewing [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Category:Pages_using_article_guidance the outlines], please provide feedback on the [[mw:Talk:Article guidance|project talk page]]. Based on your input, the feature will be refined and transferred to the pilot Wikipedias to translate and adapt. Check out [[c:File:Article Guidance workflow demo - April 2026.webm|the video]] explaining the feature. '''Updates for editors''' * On most wikis, all autoconfirmed users can now use [[Special:ChangeContentModel|Special:ChangeContentModel]] page to [[mw:Special:MyLanguage/Help:ChangeContentModel|create new pages with custom content models]], such as mass message lists, making custom page formats more accessible. Check [[Special:ListGroupRights|Special:ListGroupRights]] for the status of your wiki. [https://phabricator.wikimedia.org/T248294] * The Growth team has launched an [[mw:Special:MyLanguage/Contributors/Account_Creation_Experiments|account creation experiment]] to evaluate whether adding an account creation button to the mobile web header increases new account registrations and encourages more mobile users to contribute to the wikis. The experiment is currently live on Hindi, Indonesian, Bengali, Thai, and Hebrew Wikipedia, and targets 10% of logged-out mobile web users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:30}} community-submitted {{PLURAL:30|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, an issue where VisualEditor could get stuck loading on Windows devices with animations turned off, has now been fixed. [https://phabricator.wikimedia.org/T382856] '''Updates for technical contributors''' * Starting later this week, {{int:group-abusefilter}} who have the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature enabled will have [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] as the editor at [[Special:AbuseFilter|Special:AbuseFilter]]. This is part of the broader effort to make the user experience more consistent across all editors. [https://phabricator.wikimedia.org/T399673][https://phabricator.wikimedia.org/T419332] * Tools and bots that access the [[mw:Special:MyLanguage/Notifications/API|Notifications API]] (<bdi lang="zxx" dir="ltr"><code><nowiki>action=query&meta=notifications</nowiki></code></bdi>) will need to update their OAuth or BotPassword grants to also include access to private notifications. [https://phabricator.wikimedia.org/T421991] * Due to a library upgrade, listings on category pages may be displayed out of order starting on Monday, 20th April. A migration script will be run to correct this, and will take hours to days depending on the size of the wiki (up to a week for English Wikipedia). [https://phabricator.wikimedia.org/T422544] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.24|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/16|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W16"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 13 avril 2026 à 17:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30380527 --> == Actualités techniques n° 2026-17 == <section begin="technews-2026-W17"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/17|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Après deux ans de développement, la version [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]], également connue sous le nom de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], sortira de sa phase bêta le mardi 21 avril. Elle offrira une meilleure lisibilité du code et du wikitext, une réduction des fautes de frappe et d'autres [[mw:Special:MyLanguage/Help:Extension:CodeMirror|avantages]] à tous les utilisateurs du surligneur de syntaxe standard. Un grand merci au bénévole [https://phabricator.wikimedia.org/p/Bhsd/ Bhsd] qui a développé de nombreuses nouvelles fonctionnalités, notamment [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Code folding|le repliement de code]], [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Autocompletion|la saisie semi-automatique]] et [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Linting|l'analyse statique du code]]. [https://phabricator.wikimedia.org/T259059] * Une mise à jour majeure de l'application Wikipédia pour iOS est en cours de déploiement, en restructurant l'interface pour s'harmoniser avec le tout nouveau design visuel "Liquid Glass" d'Apple. [https://apps.apple.com/us/app/wikipedia/id324715238 Télécharger la dernière version] et découvrez les nouveautés. '''Actualités pour la contribution''' * [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|Les listes de lecture]] est une fonctionnalité qui permet aux lecteurs d'enregistrer des articles dans une liste pour les lire ultérieurement. Cette fonctionnalité est actuellement en version bêta sur les Wikipédias en arabe, français, indonésien, vietnamien et chinois, et activée par défaut pour tous les nouveaux comptes sur toutes les Wikipédias. * Une expérimentation visant à étendre [[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews|les aperçus de page au web mobile]] sera lancée la semaine du 20 avril sur les versions arabe, anglaise, française, italienne, polonaise et vietnamienne de Wikipédia. Les aperçus de page sont des fenêtres contextuelles affichant une miniature, un premier paragraphe et un lien bleu permettant d'ouvrir l'article complet, facilitant ainsi la découverte de contenu. Cette fonctionnalité est déjà disponible sur ordinateur et dans les applications. [[m:Special:MyLanguage/List of experiments in Product and Technology#Template|En savoir plus sur cette expérimentation et d'autres]]. * Sur plusieurs wikis, les contributeurs connectés qui n'ont pas [[mw:Special:MyLanguage/Help:Email confirmation|confirmé leur adresse électronique]] peuvent désormais voir une bannière les invitant à le faire. La confirmation de l'adresse électronique permet à un utilisateur de récupérer l'accès à son compte en cas de perte. [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security#Encouraging users to confirm their email addresses|En savoir plus]]. [https://phabricator.wikimedia.org/T421366] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:15|la tâche soumise|les {{formatnum:15}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:15||s}} la semaine dernière]]. Par exemple, un problème qui entraînait des ralentissements lors de la modification de très grandes pages wiki dans l'éditeur wikitext de 2017, des problèmes de chargement, de prévisualisation et de défilement, ainsi que des problèmes de performance lors de la sélection, de la découpe ou du collage de contenu, a maintenant été résolu. [https://phabricator.wikimedia.org/T184857] '''Actualités pour la contribution technique''' * Dans le cadre de la promotion de [[mw:Special:MyLanguage/Help:Extension:CodeMirror|CodeMirror]] à partir d'une fonctionnalité bêta, tous les utilisateurs se serviront de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] au lieu de [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] pour la coloration syntaxique lors de l'édition de pages de contenu JavaScript, CSS, JSON, Vue et Lua. [https://phabricator.wikimedia.org/T419332] * <span class="mw-translate-fuzzy">Le service <code>mirrors.wikimedia.org</code> pour les utilisateurs de Debian et Ubuntu sera définitivement arrêté le 15 mai. Le matériel du serveur sera remplacé par des solutions plus performantes. Certains utilisateurs devront peut-être migrer vers un autre serveur qui ne devra prendre qu'une minute. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/LJYRIS4WB66HIRCAO4GIDTXCMDVZRBMA/ Vous pouvez en savoir plus].</span> [https://phabricator.wikimedia.org/T416707] * Les tables <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi> seront supprimées de [[wikitech:Help:Wiki Replicas|wikireplicas]]. Si vos outils ou requêtes accèdent directement à <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> ou <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi>, veuillez les mettre à jour pour utiliser les tables <bdi lang="zxx" dir="ltr"><code><nowiki>file</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>filerevision</nowiki></code></bdi> avant le 28 mai. [https://phabricator.wikimedia.org/T28741] * Suite à la récente mise en place de limites de débit globales pour les API non identifiées, la Fondation Wikimedia poursuit ses efforts pour garantir [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|une utilisation équitable de l'infrastructure]] en appliquant des limites globales au trafic des API identifiées à partir de la dernière semaine d'avril. Ces limites sont volontairement fixées au niveau le plus élevé possible afin de minimiser l'impact sur la communauté. Les bots exécutés dans Toolforge/WMCS ou disposant des droits d'utilisateur de bot sur un wiki ne devraient pas être affectés pour le moment. Toutefois, il est conseillé à tous les développeurs de suivre les bonnes pratiques mises à jour. Pour plus d'informations, consultez la page [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|API Wikimedia/Limites de débit]] et la [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits/FAQ|Foire aux questions]]. * L'[[mw:Special:MyLanguage/Attribution API|API d'attribution]] est désormais disponible en [[mw:Special:MyLanguage/Wikimedia APIs/Stability policy|version bêta]]. Elle récupère les informations nécessaires pour créditer les articles et les fichiers multimédias de Wikimedia, quel que soit leur lieu d'utilisation. La documentation de référence est disponible sur la page dédiée au Sandbox REST, accessible sur tous les wikis Wikimedia (comme [https://en.wikipedia.org/w/index.php?api=attribution.v0-beta&title=Special%3ARestSandbox le sandbox REST de Wikipédia en anglais]). N'hésitez pas à partager vos commentaires sur la [[mw:Talk:Attribution API|page de discussion du projet]]. * Il n'y aura pas de nouvelle version de MediaWiki cette semaine. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/17|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W17"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20 avril 2026 à 17:00 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30432763 --> == Request for comment (global AI policy) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies for writing in English. {{int:Please-translate}} A [[:m:Requests for comment/Artificial intelligence policy|request for comment]] is currently being held to decide on a global AI policy. {{int:Feedback-thanks-title}} [[Utilisateur:MediaWiki message delivery|MediaWiki message delivery]] ([[Discussion utilisateur:MediaWiki message delivery|discussion]]) 26 avril 2026 à 02:57 (CEST) </bdi> <!-- Message envoyé par User:Codename Noreste@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30424282 --> == Actualités techniques n° 2026-18 == <section begin="technews-2026-W18"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/18|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * Un changement dans la manière dont les utilisateurs et utilisatrices sont automatiquement confirmés est en cours pour améliorer la protection contre le vandalisme. Actuellement, il suffit d’avoir un compte depuis quelques jours avec quelques contributions pour être ajouté au groupe [[{{int:grouppage-autoconfirmed/{{CONTENTLANGUAGE}}}}|{{int:group-autoconfirmed}}]]. Cette configuration tend à être exploitée par certains vandales qui créent des comptes et commencent à les utiliser après un certain temps. Pour réduire ce problème, la configuration va changer la semaine prochaine afin que l’âge du compte minimum pour être confirmé automatiquement ne soit calculé qu’à partir de la première modification, au lieu de la date d’inscription. L’âge minimum du compte restera le même, c’est seulement le point de départ pour calculer cet âge qui change. Ce changement ne sera déployé que sur les wikis qui nécessitent au moins une contribution pour satisfaire les conditions de confirmation automatique. [https://phabricator.wikimedia.org/T418484] * Tous les utilisateurs et utilisatrices de Wikipédia avec un nouveau compte et ceux qui ont activé l’option « activer automatiquement la plupart des fonctionnalités bêta » peuvent désormais utiliser la fonctionnalité bêta de [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|listes de lecture]] pour enregistrer des articles à lire plus tard. Cela permet d’organiser les lectures qui nous intéressent à un endroit unique pour y accéder facilement. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:30|la tâche soumise|les {{formatnum:30}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:30||s}} la semaine dernière]]. Par exemple, le problème avec les images d’infoboite qui avaient une marge intérieure immense dans Firefox a été corrigé. [https://phabricator.wikimedia.org/T423676] '''Actualités pour la contribution technique''' * Pour rappel, la limite globale d’accès à l’API sera appliquée cette semaine pour identifier le trafic de l’API. Le but est d’aider à garantir un [[mw:MediaWiki Product Insights/Responsible Reuse|accès équitable à l’infrastructure]]. Les robots qui s’exécutent dans Toolforge ou WMCS, ou avec le droit utilisateur ''robot'' sur les wikis, ne devraient pas être affectés pour le moment. Cependant, il est conseillé à tous les développeurs et développeuses de se conformer aux nouvelles bonnes pratiques à suivre. Pour plus d’informations, notamment la limite globale d’accès effective, consultez [[mw:Wikimedia APIs/Rate limits|la page sur la limite d’accès des API de Wikimedia]] et les [[mw:Wikimedia APIs/Rate limits/FAQ|questions-réponses]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.26|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/18|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W18"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 27 avril 2026 à 20:06 (CEST) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30458046 --> == Actualités techniques n° 2026-19 == <section begin="technews-2026-W19"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/19|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L’équipe chargée des fonctionnalités de [[mw:Special:MyLanguage/Article guidance|Guidage des articles]] invite les contributeurs et contributrices expérimentés des [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators|Wikipédia pilotes]] (arabe, bangla, japonais, portugais, persan, turc, anglais simplifié, espagnol et français) à contribuer à la traduction et à l’adaptation des [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Category:Pages_using_article_guidance exemples de trames d’articles]. Ces trames guideront les contributeurs dans la création d’articles clairs, bien structurés et conformes aux règles lors de l’utilisation de [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Special:NewArticle la fonctionnalité] dès son lancement en mai 2026. Des [[mw:Special:MyLanguage/Article guidance#Adapting a sample outline in a Wikipedia|instructions simples]] expliquant comment traduire et adapter ces trames sont disponibles. '''Actualités pour la contribution''' * Le [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif sur les produits et les technologies]] a publié [[:m:Special:MyLanguage/Product and Technology Advisory Council/May 2026 draft PTAC recommendation for feedback|une proposition de recommandation]] d’une procédure type que les organisations affiliées à Wikimedia pourraient suivre pour contribuer au domaine technique. Les membres de la communauté sont invités à donner leur avis sur cette recommandation avant le 8 mai [[:m:Talk:Product and Technology Advisory Council/May 2026 draft PTAC recommendation for feedback|sur la page de discussion]]. * Le nombre de préférences de taille de la miniature disponibles dans MediaWiki va être réduit à trois options standardisées : ''petite'' (180 px), ''moyenne'' (250 px) et ''large'' (400 px), dans le cadre du travail en cours pour améliorer les performances et réduire la pression sur les services de miniatures. Par conséquent, les préférences existantes seront automatiquement adaptées à la nouvelle taille la plus proche (par exemple, les petites tailles comme 120 px ou 150 px s’afficheront à 180 px, tandis que les grandes tailles comme 300 px ou 360 px s’afficheront à 400 px). L’interface des préférences sera bientôt mise à jour pour refléter ces changements, et les utilisateurs qui souhaitent s’y opposer ou donner leur avis peuvent le faire. [https://phabricator.wikimedia.org/T424909] * Dorénavant, même lorsqu’une permission expire automatiquement, les utilisateurs recevront une notification Echo similaire à la notification normale pour les changements de permissions. Quant au [[m:Special:MyLanguage/Global reminder bot|robot global de rappel]], il continue de prévenir les utilisateurs une semaine ''avant'' que leurs droits ne soient sur le point d’expirer, afin qu’ils puissent les faire renouveler. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:32|la tâche soumise|les {{formatnum:32}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:32||s}} la semaine dernière]]. Par exemple, le problème du sélecteur de langue ULS dans [[m:Special:Translate|Special:Translate]] qui faisait défiler verticalement alors qu’il ne devait pas, a été résolu. Auparavant, lorsque les utilisateurs ouvraient le menu déroulant « Traduire en français » et commençaient à saisir le nom d’une langue, la boîte de dialogue défilait verticalement de quelques pixels même lorsqu'il y avait suffisamment d’espace pour afficher tous les résultats. Le menu déroulant ne se déplace plus inutilement lors du filtrage des langues. [https://phabricator.wikimedia.org/T358864] * La [[m:Special:GlobalWatchlist|liste de suivi globale]], qui vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page, continue de s’améliorer. Par exemple, les listes de suivi pour les sites avec Wikibase tels que [[:d:|Wikidata]] prennent désormais en charge les éléments [[mw:Special:MyLanguage/Extension:EntitySchema|EntitySchema]] pour un meilleur suivi. Le mode Mises à jour en direct actualise désormais la page spéciale toutes les 60 secondes afin de se conformer aux [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|nouvelles limites globales d’accès à l’API]] pour une meilleure réactivité en temps réel. Par ailleurs, un bug de directionnalité du texte qui affichait les liens comme « changements 3 » au lieu de « 3 changements » dans les listes à directions mixtes a été corrigé. [https://phabricator.wikimedia.org/T415450][https://phabricator.wikimedia.org/T424422][https://phabricator.wikimedia.org/T418091] '''Actualités pour la contribution technique''' * La deuxième phase de [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|limitations globales d’accès à l’API]] a été déployée pour réduire l’[[diffblog:2026/03/26/quo-vadis-crawlers-progress-and-whats-next-on-safeguarding-our-infrastructure/|impact des robots IA]] et assurer un accès équitable et durable aux ressources de Wikimedia, en donnant la priorité au trafic humain et conforme à notre mission. Les [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits#Limits|limites]] ne s’appliquent plus par heure mais par minute, produisant une meilleure répartition dans les structures de trafic ainsi qu’une meilleure prévisibilité de la charge de l’API. Les utilisateurs de la communauté ne devraient pas être affectés, et aucune action n’est requise. Les premières indications montrent que certains requérants basés sur l'agent utilisateur ajustent leur comportement, et environ 64 % du trafic API automatisé a été identifié. La surveillance continue, et Wikimedia Enterprise reste disponible pour l’assistance commerciale. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.27|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/19|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W19"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 4 mai 2026 à 22:43 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30498077 --> == Actualités techniques n° 2026-20 == <section begin="technews-2026-W20"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/20|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * La Communauté Technique a publié [[m:Special:MyLanguage/Community Wishlist/How to write a good wish|de nouvelles directives]] expliquant comment les souhaits sur la Liste de souhaits de la communauté sont triés et priorisés. La documentation vise à aider les contributeurs à rédiger des propositions plus solides en clarifiant les facteurs qui influencent les décisions de priorisation. Au-delà du nombre de votes, les directives mettent en avant des considérations telles que l'impact potentiel sur la communauté pour déterminer quels souhaits avanceront. '''Actualités pour la contribution''' * L'équipe de croissance des lecteurs lance une expérience pour tester une nouvelle [[mw:Special:MyLanguage/Readers/Reader_Growth/Share_Card|fonctionnalité de Partage de Carte]] qui permet aux lecteurs de créer des cartes visuellement attrayantes à partir d'articles Wikipédia ou de sections d'articles sélectionnées et de les partager en ligne, chaque carte renvoyant à l'article original afin d'aider à augmenter le lectorat et la découverte des articles. Le test A/B réservé aux mobiles ne sera disponible qu'à une partie des lecteurs sur les Wikipédia en arabe, chinois, français, vietnamien et anglais afin de mieux comprendre les habitudes de lecture et de partage, et est prévu pour commencer la semaine du 18 mai pour une durée de quatre semaines. * Les applications Wikipedia pour Android et iOS ont récemment publié en version bêta le [[mw:Special:MyLanguage/Wikimedia_Apps/Team/25th_Birthday_Reading_Challenge|défi de lecture de 25 jours]], dans le cadre des efforts visant à stimuler l'engagement des lecteurs en encourageant les utilisateurs à atteindre des objectifs de lecture. Pour suivre leur série de lectures pendant le défi, les utilisateurs de l'application peuvent ajouter un widget avec Baby Globe à leur écran d'accueil. Le défi commence officiellement le 11 mai. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:17|la tâche soumise|les {{formatnum:17}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:17||s}} la semaine dernière]]. Par exemple, un problème où la préférence globale pour activer la coloration syntaxique dans le wikitexte pouvait s'éteindre de manière inattendue après avoir été activée a maintenant été corrigé. [https://phabricator.wikimedia.org/T425286] '''Actualités pour la contribution technique''' * [[File:Octicons-tools.svg|12px|link=|alt=|Sujet technique]] Le module ResourceLoader <bdi lang="zxx" dir="ltr"><code><nowiki>mediawiki.ui.input</nowiki></code></bdi>, obsolète depuis [[m:Special:MyLanguage/Tech/News/2023/39|septembre 2023]], sera supprimé cette semaine. Il existe un [[mw:Special:MyLanguage/Codex/Migrating_from_MediaWiki_UI|guide pour migrer de l’interface MediaWiki UI vers Codex]] pour tous les outils qui l’utilisent. [https://phabricator.wikimedia.org/T420125] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.2|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/20|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W20"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 11 mai 2026 à 21:20 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30524429 --> == Actualités techniques n° 2026-21 == <section begin="technews-2026-W21"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/21|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L'équipe de Wikipédia abstraite a identifié cinq wikis pilotes potentiels pour évaluer leur intérêt à adopter des articles abstraits sur leurs wikis. Les pilotes sont Wikipédia en Malayalam, en Bengali, en Dagbani, en Arabe et en Indonésien. La période de retour d'information sera ouverte jusqu'au 22 mai. Si votre communauté est intéressée à devenir un pilote, [[m:Talk:Abstract Wikipedia|faites-nous savoir sur Meta]]. '''Actualités pour la contribution''' * Une expérience visant à afficher [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|les listes de lecture]] aux lecteurs non connectés sur le web mobile sera lancée le 18 mai sur les Wikipédias Allemande, Espagnole, Italienne, Portugaise, Polonaise, Néerlandaise, Turque et Ourdou, et durera un mois. Cet effort soutient des objectifs plus larges consistant à aider les lecteurs à enregistrer et organiser des articles pour une lecture ultérieure, tout en encourageant des habitudes qui pourraient mener à de futures contributions sur Wikipédia. * Pour prendre en charge un bouton de marquage dans la fonctionnalité bêta Liste de lecture, le menu "Outils > Action" a été mis à jour pour afficher des icônes, y compris l'indicateur en forme d'étoile de suivi qui aide les éditeurs à identifier les articles suivis temporairement. Les icônes correspondent désormais également à celles utilisées sur mobile, améliorant la cohérence entre les plateformes. Le changement est actuellement limité au menu des actions et concerne principalement les éditeurs ayant des droits d'utilisateur privilégié. [https://phabricator.wikimedia.org/T426008] * [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Mode de Suggestion]] a été publié en tant qu'[[w:en:A/B test|test A/B]] pour les nouveaux éditeurs sur le site mobile à [[phab:T421189|~15 Wikipédias]]. L'expérience mesurera l'impact que le Mode de Suggestion a sur la proportion de sessions d'édition sur le web mobile par des nouveaux éditeurs qui aboutissent à des modifications constructives (non annulées) des articles. L'expérience évaluera également l'impact de la fonctionnalité sur la rétention des éditeurs et surveillera les changements dans les taux d'annulation et de blocage. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, un problème dans l'application Android de Wikipédia où les images pourraient parfois ne pas se charger après avoir ouvert une notification de liste de lecture recommandée, a maintenant été corrigé. [https://phabricator.wikimedia.org/T418231] '''Actualités pour la contribution technique''' * L'[[mw:Special:MyLanguage/Wikidata Platform|équipe de la Plateforme Wikidata]] a publié sa [[d:Special:MyLanguage/Wikidata:SPARQL query service/WDQS backend update/Backend Replacement|recommandation de remplacement du backend]] et l'[[wikitech:Wikidata Query Service/WDQS Architecture re-design|architecture technique]] qui l'accompagne pour la migration du Wikidata Query Service (WDQS) hors de Blazegraph grap. Les retours sont attendus jusqu'au 25 mai 2026, en particulier sur les éventuelles lacunes et impacts sur les cas d'utilisation avancés. Les membres de la communauté Wikidata et les utilisateurs de WDQS sont également encouragés à aider à identifier les outils et flux de travail à fort impact qui pourraient nécessiter une attention sur [[d:Wikidata:SPARQL query service/WDQS backend update/High-Impact Use Cases|cette page]]. Les retours peuvent être partagés sur la [[d:Wikidata talk:SPARQL query service/WDQS backend update|page de discussion de la migration]] ou lors de la [[d:Special:MyLanguage/Wikidata:Blazegraph Migration Office Hours|prochaine heure de bureau]]. Voir le [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|bulletin de l'équipe WDP]] pour plus de détails. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.3|MediaWiki]] '''En détails''' * Sur les Wikipédia en anglais, en français, en japonais et quelques autres, il y a eu un [[diffblog:2025/09/02/better-detecting-bots-and-replacing-our-captcha/|essai de hCaptcha]], un service tiers de détection de robots. L'essai a montré que hCaptcha détecte et dissuade efficacement certaines activités automatisées de mauvaise foi, à la fois par lui-même et en donnant des signaux aux [[w:en:Wikipedia:Village pump (technical)/Archive 225#Introducing SuggestedInvestigations|checkusers et stewards]] pour qu'ils enquêtent. Comme les résultats étaient positifs, hCaptcha sera déployé sur toutes les wikis au cours des prochaines semaines. [[mw:Special:MyLanguage/Product Safety and Integrity/Anti-abuse signals/hCaptcha|Voir la page du projet hCaptcha]] pour des informations techniques sur la mise en œuvre et les protections de la vie privée. [[diffblog:2026/05/04/better-detecting-bots-and-replacing-our-captcha-part-2/|En savoir plus]]. * La dernière mise à jour de la Technologie communautaire est désormais disponible, avec des progrès dans plusieurs initiatives de la Liste de souhaits communautaire, y compris l'extension des listes de lecture de l'application mobile au site web, la prise en charge de nouvelles langues pour "Who Wrote That" et le Tableau de bord personnel, des améliorations du rendu 3D et des graphiques, ainsi que des travaux à venir sur le tri des pages de discussion, la lecture audio et les flux de travail d'édition. La mise à jour partage également les priorités actuelles, les tendances de l'état de la Liste de souhaits et les opportunités de retour d'information de la communauté sur les domaines de concentration futurs et le Plan annuel 2026–2027 de la Wikimedia Foundation. [[m:Special:MyLanguage/Community Wishlist/Updates#May 13, 2026: Latest updates from the Community Tech team|Lisez le bulletin d'information complet pour plus de détails]]. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/21|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W21"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 18 mai 2026 à 22:21 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30539262 --> == Actualités techniques n° 2026-22 == <section begin="technews-2026-W22"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/22|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Faisant suite à une [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#LOWM|expérience fructueuse sur la création de comptes]], un message d'avertissement pour les personnes déconnectées sera déployé sur les wikis Wikimédia durant la première semaine de juin. Ce changement n'affectera que les personnes déconnectées sur l'interface web mobile qui commencent à modifier. Cette nouvelle expérience est faite pour encourager la création de comptes, tout en autorisant aux utilisateurs de modifier à l'aide de comptes temporaires. Les résultats de l'expérience ont montré une augmentation de la création de compte d'environ 27 % pour ceux ayant vu le nouveau message. Comme prévu, puisque plus de personnes créent un compte, la création de comptes temporaires a diminué de 16 %. L'expérience n'a pas montré d'autres changements sur la qualité des modifications ou sur les autres indicateurs surveillés. [https://phabricator.wikimedia.org/T424595] '''Actualités pour la contribution''' * Pour des raisons de sécurité, les membres de certains groupes d’utilisateurs sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir l'authentification à 2 facteurs]] (A2F) d'activée. Les membres de ces groupes seront dans l'impossibilité de désactiver la dernière méthode d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Ces utilisateurs auront toujours la possibilité d'ajouter ou d'enlever des nouvelles méthodes d'authentification, tant qu'une de ces méthodes est toujours activée. Dans les prochaines semaines, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique entre autres aux bureaucrates. Veuillez lire les tâches liées pour les dates de déploiement. [https://phabricator.wikimedia.org/T423119][https://phabricator.wikimedia.org/T423120] * L'[[m:Special:MyLanguage/WMDE Technical Wishes|équipe des souhaits techniques de Wikimédia Allemagne (WMDE)]] va lancer un [[w:fr:Test A/B|test A/B]] sur [[:phab:T415904|10 wikis]], pour essayer des [[m:WMDE Technical Wishes/References/Reference Previews|améliorations potentielles pour les aperçus de références]]. Cette expérience durera environ 2 semaines à la fin mai ou début juin et affectera 10 % du lectorat sur ordinateur sur les wikis participants. * Après deux expériences fructueuses, l'équipe Croissance du lectorat déploiera une fonctionnalité de [[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|visionnage d'images]] en bêta pour toutes les Wikipédia sur mobile le 25 mai. Cela veut dire que toutes les personnes ayant les fonctionnalités bêtas activées verront cette fonctionnalité. Les autres pourront l’activer dans leurs préférences. Cette fonctionnalité inclura un carrousel de toutes les images d'un article en haut de celui-ci, avec la possibilité pour les contributeurs d’[[mw:Readers/Reader_Growth/Image_Browsing#Phase_2.1_beta_feature|exclure des images du carrousel d'un article ou d'enlever la fonctionnalité pour l'entièreté de l'article]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:30|la tâche soumise|les {{formatnum:30}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:30||s}} la semaine dernière]]. Par exemple, les fichiers STL tridimensionnels étaient affichés incorrectement par l'extension 3D du lecteur multimédia, ce qui est maintenant corrigé. [https://phabricator.wikimedia.org/T416723] '''Actualités pour la contribution technique''' * Les classes CSS dépréciées <bdi lang="zxx" dir="ltr"><code><nowiki>tleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>tright</nowiki></code></bdi> ont été remplacées par <bdi lang="zxx" dir="ltr"><code><nowiki>floatleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>floatright</nowiki></code></bdi> car les premières ne fonctionnent pas correctement sur toutes les plateformes, dont l'interface web mobile et l'application mobile. Les projets se servant de ces classes sont encouragés à vérifier leur usage et à planifier leur migration. Sachez que <bdi lang="zxx" dir="ltr"><code><nowiki>floatleft</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>floatright</nowiki></code></bdi> pourraient aussi être dépréciées dans le futur, même s’il n'y a pas de calendrier défini. [[phab:T426452|En savoir plus]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.4|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/22|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W22"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 25 mai 2026 à 23:52 (CEST) <!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30584502 --> == Votez maintenant aux élections 2026 de l'U4C == <section begin="announcement-content" /> Les votants éligibles sont invités à participer à l'élection 2026 du [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Comité de coordination du Code de conduite universel]]. De plus amples informations – notamment sur la vérification de l'éligibilité, le processus de vote, les candidats et un lien vers le scrutin – sont disponibles sur Meta à la [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|page d'informations sur les élections de 2026]]. Le scrutin se termine le 2 juin 2026 à [https://zonestamp.toolforge.org/1780358400 00 h 00 UTC]. Veuillez voter si votre compte est éligble. Les résultats seront disponibles avant le 14 juin 2026. -- en coopération avec l'U4C.<section end="announcement-content" /> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 27 mai 2026 à 19:14 (CEST) <!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == Actualités techniques n° 2026-23 == <section begin="technews-2026-W23"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/23|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * L'équipe [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience]] mène une expérience pour montrer la fonctionnalité [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|listes de lecture]], qui est encore en développement, aux lecteurs non connectés sur mobile afin de tester si elle encourage la création de compte à un rythme plus élevé que le bouton watchstar. L'[[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists#Experiment timeline|expérience]] a été lancée le 18 mai sur les wikis en allemand, espagnol, italien, portugais, polonais, néerlandais, turc et ourdou, et elle durera un mois. * L'équipe Wikimedia Apps a publié la [[mw:Special:MyLanguage/Wikimedia Apps/Team/Explore Feed Refresh/Phase 1|Phase 1]] du flux d'accueil repensé pour l'application Android Beta. Le nouveau flux d'accueil comprend un onglet « Communauté » actualisé et un onglet « Pour vous » personnalisé contenant des recommandations de lecture mises à jour quotidiennement. La refonte fait partie d'un effort plus large visant à améliorer la découverte de contenu et à créer des expériences d'apprentissage plus engageantes dans les applications Wikipédia. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:18|la tâche soumise|les {{formatnum:18}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:18||s}} la semaine dernière]]. Par exemple, un problème où les images pouvaient ne pas se charger pour certaines modifications suggérées sur [[w:Special:Homepage|Special:Homepage]], laissant la vignette bloquée dans un état de chargement, a maintenant été corrigé. [https://phabricator.wikimedia.org/T424048] '''Actualités pour la contribution technique''' * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.5|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/23|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W23"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 1 juin 2026 à 23:08 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30613639 --> == Actualités techniques n° 2026-24 == <section begin="technews-2026-W24"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/24|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Wikimedia Entreprise a relevé les limites d’utilisation gratuite de ses API. La limite mensuelle de requêtes pour l’API « à la demande » (<i lang="en">On-demand</i>) est passée de {{formatnum:5000}} à {{formatnum:50000}} requêtes, tandis que celle de l’API des instantanés (<i lang="en">Snapshot</i>) est passée de 15 à 30 requêtes par mois. De plus, les instantanés de contenus structurés sont désormais accessibles aux comptes gratuits. Ces changements élargissent l’accès aux données de Wikimedia Entreprise pour les développeurs et développeuses, les chercheurs et chercheuses et les organisations qui utilisent les contenus Wikimédia. [https://enterprise.wikimedia.com/blog/enhanced-free-api] '''Actualités pour la contribution''' * La [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Explore Feed Refresh/Phase 1|nouvelle version du Fil d’exploration]], désormais appelé « Fil d’accueil », est en cours de déploiement auprès de 50 % des utilisateurs de l’application Wikipédia pour Android. Le fil d’accueil aide le lectorat à découvrir du contenu pertinent grâce à deux nouveaux onglets : « Communauté » et « Pour vous ». L’onglet « Communauté » propose un flux défilant de contenus sélectionnés et d’actualités provenant de l’ensemble de la communauté et du mouvement Wikimédia, tandis que l’onglet « Pour vous » offre une expérience en plein écran et par glissement qui présente des contenus adaptés aux centres d’intérêt de l’utilisateur ou utilisatrice. Cette refonte s’inscrit dans le cadre d’un travail en cours visant à améliorer la découverte et à enrichir l’expérience d’apprentissage au sein de l’application Wikipédia. * Le jeu-questionnaire quotidien [[mw:Special:MyLanguage/Wikimedia Apps/Team/iOS/"Which came first?" Game|Qu’est-ce qui est arrivé en premier ?]] est désormais disponible dans la version bêta de l’application Wikipédia pour iOS en anglais, allemand, français, portugais, russe, espagnol, arabe, chinois et turc. Le jeu s’appuie sur des événements historiques tirés de la rubrique « Éphéméride » de Wikipédia et met les lecteurs au défi de deviner lequel des deux événements s’est produit en premier. Le jeu avait déjà été lancé sur Android. Les communautés souhaitant rendre le jeu disponible dans leur langue peuvent [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Games#Game availability by language|consulter les instructions et les conditions requises]]. * [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|Les sous-références]], une nouvelle fonctionnalité de MediaWiki permettant aux contributeurs de réutiliser des références avec des détails différents, va commencer à être déployée sur les wikis Wikimédia après une phase pilote réussie. Le déploiement débutera le 8 juin pour la plupart des [[wikitech:Deployments/Train#Wednesday|wikis du groupe 1]] et Wikipédia en français, puis d'autres éditions linguistiques de Wikipédia bénéficieront de cette fonctionnalité au cours des prochains mois. Les communautés sont invitées à se préparer en vérifiant s’il existe des [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-cite&language=en&action_source=search&filter=%21translated&optional=1&action=translate messages non traduits de l’extension Cite] dans leur langue et en passant en revue toute utilisation de l’outil [[mw:Special:MyLanguage/Reference Tooltips|Infobulles des références]], qui pourraient nécessiter des [[:phab:T416304#11668731|mises à jour]] pour prendre en charge la nouvelle fonctionnalité. Les wikis utilisant les [[mw:Special:MyLanguage/Help:Reference Previews|aperçus de référence]] n’ont aucune action à entreprendre. Les communautés peuvent également créer la [[Special:TrackingCategories|catégorie de suivi]] ''cite-tracking-category-ref-details'' en tant que catégorie cachée à l’aide de <code><nowiki>__HIDDENCAT__</nowiki></code> (ou d’un modèle dédié), et la relier à l’élément Wikidata correspondant [[d:Q129764848]]. [https://phabricator.wikimedia.org/T425662] * L'[[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews#Experimentation|expérience d'Aperçus de page]] sur le Web mobile a pris fin. L'équipe a décidé de ne pas déployer cette fonctionnalité après que les résultats ont montré qu'elle n'avait pas d'impact statistiquement significatif sur la fidélisation des lecteurs, l'amélioration de la fidélisation étant le principal indicateur de réussite. Les « Aperçus de page », déjà disponibles sur ordinateur et dans les applications, affichent une vignette, le premier paragraphe et un lien vers l'article complet lorsque les lecteurs cliquent sur un lien bleu. L'expérience a testé cette fonctionnalité sur le Web mobile sur six versions de Wikipédia. * La [[mw:Special:MyLanguage/Codex/Design/Icons|bibliothèque d'icônes de l'interface utilisateur]] sera [[phab:T399175|mise à jour dans le courant de cette semaine ou la semaine prochaine]]. La plupart des quelque 300 icônes ont été légèrement peaufinées et une trentaine de nouvelles icônes ont été ajoutées. Ces modifications améliorent les icônes afin de les rendre plus cohérentes et plus compréhensibles, et d'offrir un meilleur équilibre visuel lorsqu'elles sont utilisées en groupe. * L'interface [[mw:Special:MyLanguage/Universal Language Selector|Sélecteur universel de langue]] (ULS) de MediaWiki, qui aide les utilisateurs à sélectionner du contenu dans d'autres langues, a été mise à jour. La nouvelle version améliore la rapidité et l'accessibilité, et les utilisateurs des projets Wikimédia peuvent désormais épingler des langues pour changer de langue plus rapidement. Le déploiement sur les sites Wikimédia se fera progressivement au cours des prochaines semaines. Vous pouvez la tester dès maintenant en tant que fonctionnalité bêta en sélectionnant [[Special:Preferences#mw-prefsection-betafeatures|les fonctionnalités bêta]] dans les préférences de votre profil et partager vos commentaires sur [[mw:Special:MyLanguage/Universal Language Selector/New ULS|la page du projet]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:21|la tâche soumise|les {{formatnum:21}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:21||s}} la semaine dernière]]. Par exemple, un problème du le tableau de bord d'analyse des pages vues sur pageviews.wmcloud.org qui a arrêté de mettre à jour les données graphiques en mai 2026, affectant tous les utilisateurs, a été résolu. [https://phabricator.wikimedia.org/T427171] '''Actualités pour la contribution technique''' * La signature de la fonction <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink()</nowiki></code></bdi> a été simplifiée. Les développeurs peuvent désormais passer un objet de configuration à la place d'une liste de paramètres positionnels lors de la création de liens vers des portlets. L'ancienne signature de la fonction reste prise en charge à des fins de compatibilité ascendante. Par exemple, au lieu de : <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', '#', 'Stub', 'ca-stubtag', 'Add a stub tag to this page');</nowiki></code></bdi>, utilisez <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', { href: '#', text: 'Stub', id: 'ca-stubtag', tooltip: 'Add a stub tag to this page' });</nowiki></code></bdi>. Les responsables de la maintenance des scripts sont invités à passer en revue les utilisations existantes de <bdi lang="zxx" dir="ltr"><code><nowiki>addPortletLink()</nowiki></code></bdi> et à les mettre à jour si nécessaire. Cette modification sera disponible sur tous les wikis à partir du 11 juin. Merci à Gerges, bénévole de la communauté, d'avoir apporté cette amélioration. [https://phabricator.wikimedia.org/T427945] * '''Discussion sur la liste de souhaits de la communauté''': les [[m:Special:MyLanguage/Community Wishlist/Updates#May 20, 2026: Community Tech becomes a program|changements introduits]] par les équipes Produit et Technologie visent à augmenter le nombre et la complexité des souhaits exaucés, notamment par la dissolution de l'équipe Community Tech. Ils [[m:Special:MyLanguage/Community Wishlist/Updates|mènent actuellement des discussions]] sur une [[m:Talk:Community Wishlist#Proposed direction for Wishlist|orientation proposée pour la liste de souhaits]] émanant des membres de la communauté. Cela inclut des moyens de structurer le vote annuel, un meilleur suivi des souhaits, la suppression de certains domaines prioritaires et des [[m:Special:MyLanguage/Community Wishlist/Updates|mises à jour concernant le personnel]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.6|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/24|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W24"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 8 juin 2026 à 23:29 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30650573 --> == Actualités techniques n° 2026-25 == <section begin="technews-2026-W25"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/25|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * L'[[mw:Special:MyLanguage/Readers/Reader Growth|équipe chargée de la croissance du lectorat]] a lancé une fonctionnalité bêta d'[[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|exploration des images]] sur la version mobile de toutes les Wikipédias. Cette fonctionnalité affiche un carrousel d'images en haut des articles contenant au moins trois images. Les contributeurs peuvent configurer cette fonctionnalité à l'aide des commandes suivantes : pour masquer une image spécifique sur une page, utilisez soit <code>class=notpageimage</code> pour l'exclure des aperçus miniatures, soit <code>class=noviewer</code> pour l'exclure de MediaViewer. Le carrousel peut également être désactivé complètement sur une page à l'aide du mot magique <code><nowiki>__NOMEDIAVIEWERCAROUSEL__</nowiki></code>. Pour faire des retours ou signaler des bugs, rendez-vous sur la [[mw:Talk:Readers/Reader Growth/Image Browsing|page de discussion du projet]]. * Les [[mw:Special:MyLanguage/Help:Tables#class="wikitable"|Wikitables]] peuvent désormais être [[mw:Special:MyLanguage/Help:Sortable tables#Forcing the initial sort direction|triées par ordre décroissant]] dès le premier clic en ajoutant <code dir=ltr>data-sort-order="desc"</code> à la cellule d'en-tête. Auparavant, par défaut, cliquer une première fois sur l'en-tête d'une colonne entraînait un tri par ordre croissant. Cette nouveauté offre davantage de contrôle et de flexibilité pour les Wikitables, tandis que le comportement par défaut pour les clics suivants reste inchangé. [https://phabricator.wikimedia.org/T398416] '''Actualités pour la contribution''' * La fonctionnalité d'[[mw:Special:MyLanguage/Article guidance|Aide à la rédaction d'articles]] est actuellement en phase de test auprès de certains contributeurs qui créent de nouveaux articles sur les Wikipédias en anglais simplifié, en français et en turc. L'expérience débutera bientôt sur les Wikipédias en arabe et en bengali également. [[w:simple:Special:NewArticle|Cette fonctionnalité]] fournit aux contributeurs des conseils élaborés par la communauté afin de les aider à créer des articles conformes aux normes communautaires. Les contributeurs expérimentés peuvent continuer à créer ou à adapter des modèles pour des types d'articles spécifiques qui sont couramment créés par des contributeurs moins expérimentés. Ces modèles guident les contributeurs moins expérimentés dans la création d'articles de haute qualité. Un guide rapide des balises utilisées dans les modèles est disponible sur [[mw:Special:MyLanguage/Article guidance/Test feature guide#Markups in outlines|cette page]]. [[w:fr:Projet:Aide à la rédaction d'articles#Liste de plans d'aide à la rédaction|Des exemples de modèles]] pouvant être adaptés, ainsi que des instructions sur la manière de les adapter, se trouvent dans [[mw:Special:MyLanguage/Article guidance#Adapting a sample outline in a Wikipedia|cette section]] de la page du projet. * Les wikis qui souhaitent remplacer le bouton « indéfiniment » dans la page Special:Block pour les comptes temporaires (par exemple, les wikis qui bloquent les utilisateurs temporaires uniquement jusqu'à l'expiration de leur compte) pourront le faire en créant [[MediaWiki:ipb-indefinite-expiry-temporary-account]] avec la durée de blocage souhaitée. [https://phabricator.wikimedia.org/T427125] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:41|la tâche soumise|les {{formatnum:41}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:41||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * D'ici la fin du mois de juin, une chaîne « user-agent » valide sera requise pour les téléchargements automatisés de sauvegardes depuis le site dumps.wikimedia.org. Les requêtes automatisées fournissant une chaîne « user-agent » générique ou vide seront bloquées. Cette mesure [[phab:T400119|renforce l'application]] de la [[foundation:Special:MyLanguage/Policy:Wikimedia Foundation User-Agent Policy|politique relative à l'agent utilisateur]] en vigueur depuis longtemps. L'accès aux sauvegardes via Wikimedia Cloud Services restera inchangé. * La mise en place des [[mw:Wikimedia APIs/Rate limits|limites de débit des API]] à l'échelle mondiale est désormais achevée ; ces limites s'appliquent à toutes les API et sont fixées aux niveaux indiqués dans la documentation pour tous les groupes. Les bots fonctionnant sur Toolforge/WMCS ou disposant du droit d'utilisateur « bot » sur n'importe quel wiki restent exemptés. Tous les bots doivent continuer à respecter les bonnes pratiques décrites dans la documentation afin d'éviter d'être soumis à des limites de débit. * Le [https://api.wikimedia.org/wiki/Main_Page wiki du portail API] sera en lecture seule à partir de cette semaine (du 15 au 18 juin). La semaine suivante (du 22 au 25 juin), toutes les URL du wiki du portail API redirigeront vers [[mw:Wikimedia APIs|les API Wikimedia sur mediawiki.org]]. Pour en savoir plus, consultez la [[wikitech:API Portal/Deprecation|page du projet]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.7|MediaWiki]] '''Rencontres et évènements''' * Le 17 juin à 18 h (UTC), la WMF organisera une réunion sur Discord consacrée à la revue de code. L'[[mw:Special:MyLanguage/Developer Satisfaction Survey/2026|enquête sur la satisfaction des développeurs]] nous a permis de constater que les bénévoles rencontrent des difficultés avec la revue de code, et nous souhaitons discuter de ces expériences afin de trouver des solutions concrètes. Vous pouvez rejoindre la réunion [https://discord.gg/wikipedia?event=1514727511102062664 via le serveur Discord de la communauté Wikimedia]. * La [[m:Special:MyLanguage/Conferencia Wikimedia de América Latina 2026|Conférence Wikimedia d'Amérique latine]] organisera un hackathon régional qui réunira la communauté technique du mouvement Wikimedia, notamment des développeurs, des administrateurs système, des data scientists et des utilisateurs disposant de droits étendus. Les contributeurs techniques intéressés peuvent [https://docs.google.com/forms/d/e/1FAIpQLSf4osJzTHBJjQbYJk7TMVEJjTEQv7IgtsUDfP-o-qTgeRQQxw/viewform postuler à une bourse] pour y participer jusqu'au 21 juin à minuit (heure de la Bolivie, UTC-4). * Inscrivez-vous aux Wikimania Team Challenges pour participer à cet événement exceptionnel. Les défis par équipe se dérouleront en ligne et en présentiel les 21 et 22 juillet, avant la conférence Wikimania. Tout le monde est le bienvenu, quelles que soient ses compétences ou son inscription à Wikimania. Les équipes travailleront sur 10 défis importants visant à soutenir la communauté Wikimedia. Pour plus de détails, rendez-vous sur [[wmania:Special:MyLanguage/2026:Team challenges|la page des défis par équipe]] et [https://wikimedia.eventyay.com/wm/teamchallenges/ inscrivez-vous ici]. Les inscriptions se terminent le 20 juin à 23 h UTC. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/25|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W25"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 15 juin 2026 à 18:48 (CEST) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30689604 --> == Actualités techniques n° 2026-26 == <section begin="technews-2026-W26"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/26|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Les [[mw:Special:MyLanguage/Growth/Feature summary|fonctionnalités de croissance]] sont [[phab:T418115|désormais disponibles sur Wikidata]]. Cette mise à jour permet d'accéder au mentorat ([[mw:Special:MyLanguage/Help:Growth/Mentorship|s'il est configuré]]), au module Impact, au panneau d'aide et à une page d'accueil simplifiée pour les nouveaux arrivants (sans les suggestions de modifications). Les administrateurs de Wikidata continuent de paramétrer ces fonctionnalités via la configuration communautaire. '''Actualités pour la contribution''' * La page spéciale [[{{#special:RangeCalculator}}]] a été créée. Elle permet aux utilisateurs de trouver une plage d'adresses IP sans avoir à recourir à des outils externes. Jusqu'à présent, cet outil n'était accessible qu'aux CheckUsers. [https://phabricator.wikimedia.org/T268429] * Les [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-références]] sont une nouvelle fonctionnalité de MediaWiki qui permet aux contributeurs de réutiliser des références en modifiant certains détails. Elle sera déployée le 23 juin, sur la plupart des versions de Wikipédia de petite et moyenne taille. La [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#deployment|FAQ]] répertorie les mesures à prendre sur votre wiki pour faciliter ce déploiement. Consultez le [[:phab:T414094|plan de déploiement]] pour connaître les prochaines étapes. [https://phabricator.wikimedia.org/T428902] * À partir de la semaine prochaine, les utilisateurs recevront une notification lorsqu'ils seront bloqués ou débloqués pour l'édition, ou si ce blocage venait à changer. [https://phabricator.wikimedia.org/T100974] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:32|la tâche soumise|les {{formatnum:32}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:32||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * À partir de la semaine prochaine, les filtres anti-abus configurés pour « exiger une vérification par CAPTCHA » s'appliqueront également aux utilisateurs disposant du droit <code>skipcaptcha</code>, ce qui inclut la plupart des utilisateurs auto-confirmés. Les bots en sont exemptés. Ce changement ne concerne que les modifications qui déclenchent un filtre anti-abus. Le droit <code>skipcaptcha</code> continuera à exempter les utilisateurs de l'obligation de résoudre des CAPTCHA dans le cadre d'une utilisation normale des wikis. [https://phabricator.wikimedia.org/T402595] * La documentation de référence relative à l'[[wikitech:Machine_Learning/LiftWing/API|API Lift Wing]] a été déplacée du portail API vers le [https://wikitech.wikimedia.org/w/index.php?api=lift-wing&title=Special%3ARestSandbox bac à sable REST] interactif. * Le wiki du Portail API est désormais fermé. Pour consulter la documentation relative aux API, rendez-vous sur [[mw:Special:MyLanguage/Wikimedia_APIs|Wikimedia APIs sur mediawiki.org]]. À compter du 22 juin, toutes les URL du wiki du Portail API (https://api.wikimedia.org/wiki/) redirigeront vers la page de mediawiki.org. [https://phabricator.wikimedia.org/T427537] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.47/wmf.8|MediaWiki]] '''Rencontres et évènements''' * Participez à une visioconférence le 25 juin à 14 h 30 UTC pour rencontrer les stagiaires actuels de Wikimédia participant au [[mw:Google_Summer_of_Code/2026|Google Summer of Code]] et à [[mw:Outreachy/Round_32|Outreachy]]. Les stagiaires présenteront leurs projets et feront une brève démonstration du travail qu'ils ont réalisé jusqu'à présent. Les participants sont invités à [[mw:event:Google_Summer_of_Code/Summer_2026_June_Internship_open_session|partager leurs idées et leurs contacts au sein de leur communauté]]. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/26|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W26"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 juin 2026 à 15:05 (CEST) <!-- Message envoyé par User:Trizek (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30722494 --> == RFC about AI-generated content in Wikimedia Commons == <bdi lang="en" dir="ltr">Apologies for writing in English, please help translate this message to your language. You are invited to participate in a [[c:Commons:Requests for comment/Policy update for AI content|request for comment on Wikimedia Commons about a policy update for AI content]]. This may affect files that are uploaded to Wikimedia Commons for use on this project. Thank you. [[m:User:Codename Noreste|Codename Noreste]] ([[m:User talk:Codename Noreste|discussion]])</bdi> 23 juin 2026 à 19:11 (CEST) <!-- Message envoyé par User:Codename Noreste@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> d8am2rdqk7ayfelorgjbmtz0mlxm2s5 Dictionnaire de philosophie/Imagination 0 83588 768467 760055 2026-06-24T03:18:03Z PandaMystique 119061 Bot : ajout du paramètre lecture=oui au modèle {{DicoPhilo}} 768467 wikitext text/x-wiki {{DicoPhilo|Imagination|lecture=oui}} L’imagination occupe une place paradoxale dans l’histoire de la philosophie : dénoncée comme source d’illusion, elle est aussi célébrée comme condition de la connaissance, de la création artistique et de la vie morale. De Platon à la philosophie analytique contemporaine, elle sert tantôt à expliquer nos erreurs les plus tenaces, tantôt à rendre compte de nos capacités les plus élevées. == 1. Définir l’imagination : repères conceptuels == === 1.1. Une « attitude mentale » spécifique === Dans la philosophie de l’esprit contemporaine, on caractérise de plus en plus l’imagination non comme un type particulier de contenu mental (une « image », une histoire fictive, un scénario), mais comme une manière spécifique de se rapporter à un contenu. Imaginer qu’il neige à Montréal, par exemple, ce n’est ni percevoir effectivement la neige, ni croire qu’il neige, ni souhaiter qu’il neige : c’est adopter envers la proposition « il neige à Montréal » une attitude de simulation, de « faire comme si », sans s’engager sur sa vérité réelle.<ref>P. Saint-Germier, « Imagination (GP) », ''L’Encyclopédie philosophique'', en ligne : <nowiki>https://encyclo-philo.fr/imagination-gp/</nowiki>, consulté le 14 février 2026.</ref> Cette caractérisation permet de distinguer l’imagination de plusieurs autres attitudes mentales. Elle se distingue de la perception, qui nous met en rapport causal direct avec des objets effectivement présents, et qui prétend nous livrer cet état de choses comme réel pour nous ici et maintenant. Elle se distingue de la mémoire, qui revendique un rapport fidèle à un passé réel, passé qui a effectivement eu lieu. Elle se distingue aussi de la croyance, qui vise la vérité et oriente directement l’action : croire qu’il neige à Montréal doit, en principe, influencer notre manière de nous habiller si l’on s’y rend demain. Enfin, elle se distingue du désir, qui souhaite la réalisation de ce qu’il représente : désirer qu’il neige, c’est trouver souhaitable qu’il neige, alors qu’imaginer la neige ne suppose aucun engagement affectif particulier à son égard. Imaginer, au contraire, ne demande ni que l’objet imaginé existe, ni qu’on le tienne pour réel, ni même qu’on souhaite qu’il existe. Cette « neutralité ontologique » est au cœur de la définition large donnée par Shen‑Yi Liao et Tamar Gendler : l’imagination est la capacité de former des représentations mentales qui ne prétendent pas décrire la manière dont les choses sont effectivement, présentement et subjectivement pour le sujet, mais qui permettent de représenter d’autres possibilités, d’autres temps, d’autres points de vue.<ref>S.-Y. Liao et T. S. Gendler, « Imagination », ''Stanford Encyclopedia of Philosophy'', éd. E. N. Zalta, en ligne : <nowiki>https://plato.stanford.edu/entries/imagination/</nowiki>, consulté le 14 février 2026.</ref> C’est cette ouverture vers le possible, au sens le plus large, qui confère à l’imagination une importance théorique considérable. === 1.2. Imagination perceptuelle et imagination propositionnelle === Les philosophes contemporains distinguent généralement au moins deux grands types d’imagination : l’imagination dite « perceptuelle » et l’imagination dite « propositionnelle ». Dans le premier cas, le sujet semble se doter d’une quasi‑perception intérieure : il « voit dans sa tête » un chêne au bord d’un lac, un visage familier, une rue de son enfance, ou « entend intérieurement » une mélodie qu’il aime. Les contenus imaginés ont alors une tonalité sensorielle marquée : on peut les décrire comme des visions, des sons, des odeurs, des sensations motrices faibles mais néanmoins structurées. Ce sont des perceptions « décrochées » : elles ressemblent, pour le sujet, à de véritables perceptions, mais sans être causées ici et maintenant par un objet extérieur. Dans le second cas, celui de l’imagination propositionnelle, le sujet se rapporte à une proposition sans forcément lui associer une image sensorielle distincte. Imaginer qu’un animal dangereux se cache derrière un rocher, qu’un ami gagne à la loterie, ou qu’une norme morale pourrait être différente, peut consister surtout à adopter, sur un mode de « comme si », le contenu propositionnel correspondant : « il y a un danger derrière ce rocher », « mon ami vient de gagner », « dans ce monde, mentir est encouragé ». Ce qui compte alors n’est pas tant la vive présence d’images, mais le fait de traiter ces contenus comme des hypothèses à explorer, plutôt que comme des croyances établies.<ref>P. Saint-Germier, art. cit., section « Imagination perceptuelle et imagination propositionnelle » ; S.-Y. Liao et T. S. Gendler, art. cit., § 1.</ref> La distinction est importante parce que la tradition, depuis l’Antiquité, a souvent identifié l’imagination à une faculté d’images, à un « théâtre intérieur » où défileraient des tableaux plus ou moins vifs. Or il est possible d’imaginer des contenus abstraits sans image nette : un théorème que l’on suppose faux, une loi de la nature que l’on modifie pour voir ce qui en résulte, une hypothèse morale que l’on met à l’épreuve. À l’inverse, on peut aussi se contenter de « voir » en imagination un visage ou une couleur sans formuler explicitement de proposition. Les deux dimensions — perceptuelle et propositionnelle — sont souvent intriquées, mais elles n’en restent pas moins conceptuellement distinctes. === 1.3. Simuler sans se laisser contaminer : « quarantaine » et contrôle === Comprise comme faculté de simulation, l’imagination présente plusieurs traits récurrents. D’abord, elle entretient généralement un lien de ressemblance avec la réalité : l’arbre que je me représente en imagination ressemble, au moins grossièrement, à un véritable arbre, et les scénarios que je construis respectent en grande partie les structures causales que j’ai apprises dans le monde réel. Cette ressemblance n’est ni parfaite ni nécessaire, mais elle explique pourquoi l’imagination peut servir de guide, au moins approximatif, à l’action et à la prédiction. Ensuite, les représentations imaginatives sont en principe « mises en quarantaine » par rapport au reste de nos états mentaux. Tamar Gendler parle, à ce propos, de ''imaginative quarantining'' : lorsque nous imaginons qu’une pièce est en feu, nous ne fuyons pas nécessairement, parce que nous savons que nous jouons un rôle, que nous simulons un contexte sans nous y engager réellement.<ref>T. S. Gendler, ''Intuition, Imagination, and Philosophical Methodology'', Oxford, Oxford University Press, 2010, chap. 5.</ref> Les contenus imaginés ne doivent pas, en principe, entrer dans le « circuit effectif » de nos croyances et de nos décisions, sauf si nous décidons de les y intégrer après coup. Enfin, l’imagination semble, au moins en partie, sous notre contrôle volontaire. Il est difficile de croire sur commande une proposition dont on juge qu’elle est fausse, et il est impossible de percevoir un objet inexistant à la seule force de la volonté. En revanche, il est relativement facile de décider d’imaginer un chat sur la table, ou d’explorer en imagination les effets d’une décision. Ce caractère plus « souple » et plus « commandable » de l’imagination la rend particulièrement utile pour tester des hypothèses, pour « jouer » avec des possibilités sans s’y engager. Mais ce contrôle n’est jamais complet : des images peuvent s’imposer (souvenirs traumatiques, obsessions, ruminations), et des scénarios peuvent proliférer sans que l’on parvienne à les éteindre. L’imagination se situe ainsi à mi‑chemin entre la totale passivité de la perception et la stricte activité de la délibération rationnelle. === 1.4. Reproductrice et productrice === La tradition moderne oppose encore l’imagination reproductrice et l’imagination productrice (ou créatrice). L’imagination reproductrice est celle qui nous permet de rappeler des choses déjà perçues : revoir un paysage de montagne, se remémorer la voix d’un proche, rejouer mentalement une scène quotidienne. Elle travaille sur un matériau déjà donné par la perception et la mémoire. L’imagination productrice, elle, combine, déforme et amplifie ces éléments pour former des compositions inédites : un animal chimérique, une cité idéale, un univers de science‑fiction. Elle ne crée pas ex nihilo, mais elle assemble de façon nouvelle des fragments issus de l’expérience. On trouve cette intuition chez Hume : les idées de l’imagination sont, à l’origine, des « copies » plus ou moins fidèles des impressions sensibles, mais la faculté peut ensuite, de façon relativement libre, les associer et les recomposer. C’est ainsi que l’esprit peut former l’idée d’une « montagne d’or » : il juxtapose une idée de montagne et une idée d’or, toutes deux tirées de l’expérience, pour en faire un objet fantastique qu’aucun sens n’a jamais perçu.<ref>D. Hume, ''A Treatise of Human Nature'', T 1.1.1.7, éd. L. A. Selby‑Bigge, révisée par P. H. Nidditch, Oxford, Oxford University Press, 1978, p. 4.</ref> Kant reformule cette distinction dans son vocabulaire propre, en parlant d’« imagination reproductive » (chargée d’assurer la continuité de l’expérience, par exemple en rappelant un point de la trajectoire passée d’un objet) et d’« imagination productive » (qui intervient dans la synthèse originaire du multiple sensible selon des règles a priori).<ref>I. Kant, ''Critique de la raison pure'' (1781/1787), trad. A. Tremesaygues et B. Pacaud, Paris, PUF, 1987, A120–A121 et A78–A79/B103–B104.</ref> La première est proche d’un simple rappel réglé ; la seconde joue un rôle constitutif dans la possibilité même de l’expérience objective. == 2. Quelques grandes étapes historiques == === 2.1. Platon : l’ombre trompeuse de l’''eikasia'' === Chez Platon, l’imagination, désignée par le terme ''eikasia'', apparaît d’abord comme un mode inférieur de connaissance. Dans la fameuse allégorie de la caverne, au livre VII de la ''République'', des prisonniers, enchaînés depuis l’enfance, ne voient que les ombres projetées sur une paroi par des objets qui passent derrière eux. Les opinions qu’ils forment sur ces ombres relèvent, pour Platon, du stade le plus bas de la ''gnôsis'', en‑deçà même de la simple croyance (''pistis'').<ref>Platon, ''La République'', VI–VII, 509d–511e et 514a–517a, trad. G. Leroux, Paris, GF‑Flammarion, 2002.</ref> L’imagination, comprise comme rapport aux images (ombres, reflets, apparences), se tient au niveau le plus éloigné de l’Idée, c’est‑à‑dire de la réalité intelligible. Cette situation explique la double méfiance de Platon. D’un côté, l’imagination se contente de simulacres : non seulement elle ne saisit pas les Idées, mais elle ne saisit même pas les objets sensibles eux‑mêmes, seulement leurs reflets. De l’autre, elle nourrit la rhétorique et la poésie, qui jouent sur les images et les apparences pour séduire l’âme, au risque de la détourner de la vérité. Dans plusieurs dialogues (''Ion'', ''République'' livre X), Platon critique la poésie tragique et l’art mimétique, justement parce qu’ils s’adressent à l’imagination et aux émotions plutôt qu’à la raison. Il ne faut pourtant pas exagérer unilatéralement ce rejet. Platon recourt abondamment à des mythes et à des récits imagés : le mythe d’Er, le char ailé de l’âme, le mythe de Prométhée, tous mobilisent l’imagination du lecteur. Mais ces images n’ont de valeur que dans la mesure où elles restent au service de la conversion de l’âme vers l’intelligible : elles doivent être dépassées, non adorées pour elles‑mêmes. L’imagination reste donc, chez Platon, subordonnée à la dialectique. === 2.2. Aristote : la ''phantasia'' comme médiation entre sens et intellect === Aristote, dans le ''De anima'' et les traités psychologiques, accorde à la ''phantasia'' un statut plus positif et plus articulé. Il la définit comme ce par quoi naît en nous une ''phantasma'', c’est‑à‑dire une image ou apparence sensible, que ce soit en présence ou en absence de l’objet.<ref>Aristote, ''De anima'', III, 3, 428a1–2, trad. R. Bodéüs, Paris, GF‑Flammarion, 1995.</ref> Elle se distingue de la perception, parce qu’elle peut subsister lorsque l’objet n’est plus là (comme dans le rêve), et parce que la perception, pour Aristote, est toujours vraie quant à son objet propre (la vue, si elle est saine, ne peut se tromper sur la couleur en tant que telle), tandis que l’imagination peut être fausse et nous présenter des choses qui n’existent pas. Elle se distingue aussi de l’intellect (''nous''), qui saisit les universels et les essences. L’intellect ne se contente pas d’images : il s’élève à des formes générales. Pourtant, Aristote affirme qu’« il n’est pas possible de penser sans images » (''aneu phantasmatos ouk estin noein'').<ref>Aristote, ''De anima'', III, 7, 431a14–17 et 431b2–5.</ref> L’intellect humain, lorsqu’il pense, se sert de ''phantasmata'' comme d’un support. L’imagination a donc une fonction médiatrice : elle recueille, conserve et reproduit des formes sensibles qui serviront ensuite de matière à l’intellection. Elle intervient également dans l’action pratique : un animal en fuite ne se contente pas de subir des impressions sensorielles, il anticipe, par ''phantasia'', la trajectoire du prédateur ou de sa propre course. Cette position médiane, entre sens et intellect, fait de la ''phantasia'' un pivot de la vie psychique : elle est impliquée dans la mémoire, dans la représentation du temps, dans l’anticipation, dans l’évaluation des situations. La tradition aristotélicienne développera longuement ce schéma, notamment en le combinant avec la doctrine des sens internes. === 2.3. Moyen Âge : de la ''phantasia'' à l’''imaginatio'' === La scolastique médiévale hérite de cette conception et l’intègre à sa propre psychologie. Dans la classification des puissances de l’âme, l’''imaginatio'' (ou ''phantasia'') est rangée parmi les « sens internes » de l’âme sensitive, aux côtés de la mémoire et de l’« estimative » (''vis aestimativa''). Chez Thomas d’Aquin, par exemple, la ''vis imaginativa'' est la faculté qui conserve et recombine les formes sensibles reçues par les sens externes, alors que l’entendement agent (''intellectus agens'') abstrait, à partir de ces images, les espèces intelligibles universelles.<ref>Thomas d’Aquin, ''Somme de théologie'', I, q. 78, a. 4–5, trad. J.-P. Torrell, Paris, Cerf, 1999.</ref> L’imagination a donc une fonction clairement positive : sans elle, l’intellect humain n’aurait pas de matière concrète sur laquelle exercer son opération d’abstraction. Elle est au cœur des schémas médiévaux qui expliquent comment nous passons du sensible à l’intelligible. Dans l’exégèse biblique et la mystique, l’imagination joue aussi un rôle : visions, figures, symboles sont des supports à la contemplation de réalités spirituelles. En même temps, la méfiance héritée de Platon et d’Augustin demeure. Les images peuvent troubler la raison, exciter les passions, nourrir des illusions et des superstitions. Les auteurs spirituels mettent en garde contre les « représentations imaginaires » que le démon pourrait susciter, ou contre la complaisance à des scènes fantasmatiques. L’imagination est ainsi vue comme un instrument ambivalent : indispensable à la pensée humaine incarnée, mais dangereuse si elle n’est pas disciplinée par l’intellect et par la grâce. === 2.4. Descartes : faculté non essentielle mais révélatrice de l’union âme‑corps === Avec Descartes, l’imagination se voit assigner une place précise dans la nouvelle cartographie de l’âme. Dans la sixième ''Méditation'', Descartes propose l’exemple célèbre du triangle et du chiliogone. Lorsqu’il imagine un triangle, il affirme qu’il ne se contente pas d’en concevoir la définition abstraite (figure plane à trois côtés et trois angles), mais qu’il regarde pour ainsi dire ces côtés « comme présents par la force et l’application intérieure de [son] esprit ». En revanche, bien qu’il puisse concevoir clairement ce qu’est un chiliogone (un polygone à mille côtés), il ne peut pas en imaginer distinctement chacun des côtés : il ne les « voit » pas intérieurement comme il voit les trois côtés du triangle.<ref>R. Descartes, ''Méditations métaphysiques'' (1641), Méditation VI, dans ''Œuvres philosophiques'', t. II, éd. F. Alquié, Paris, Garnier, 1967, AT VII, 71–73 ; voir aussi la version française sur Wikisource : ''Méditations métaphysiques/Méditation sixième''.</ref> Cet exemple permet à Descartes de tirer plusieurs conclusions. Tout d’abord, l’imagination est une faculté distincte de l’entendement : on peut concevoir une réalité (le chiliogone) sans pouvoir se la figurer clairement. Ensuite, l’imagination n’appartient pas à l’essence de l’âme : l’ego pensant pourrait exister sans elle, comme pur sujet de pensée (''res cogitans''). Enfin, l’imagination est étroitement liée au corps : imaginer, explique Descartes, consiste en une certaine « application de la faculté qui connaît au corps qui lui est intimement présent », ce qui suggère que l’imagination manifeste, au moins confusément, l’union de l’âme et du corps.<ref>R. Descartes, ''Méditations métaphysiques'', Méditation VI, AT VII, 71–72.</ref> Dans ce cadre, la valeur épistémique de l’imagination reste modeste. Ce qui fonde la connaissance certaine, ce sont les idées claires et distinctes, saisies par l’entendement seul. L’imagination peut aider à saisir des figures géométriques, à se représenter des corps en mouvement, à rendre plus aisées certaines démonstrations, mais elle n’ajoute rien, en rigueur, à la lumière de l’intuition intellectuelle. Elle demeure pourtant philosophiquement significative, parce qu’elle signale la condition incarnée de l’homme : au contraire de Dieu ou des anges, l’esprit humain n’est pas seulement penseur, il est aussi imaginant, c’est‑à‑dire étroitement uni à un corps qui le limite et le structure. === 2.5. Hume : l’imagination comme « toile de l’esprit » === Avec Hume, au XVIIIᵉ siècle, l’imagination devient le cœur de l’explication empiriste de l’esprit. Hume commence par distinguer deux espèces fondamentales de perceptions : les impressions, qui sont les perceptions vives et originaires (sensations, passions, émotions), et les idées, qui en sont les « images affaiblies », pâles copies qui se présentent lorsque l’objet sensible n’est plus là. Sa « règle générale » (''Copy Principle'') affirme que toutes nos idées simples dérivent d’impressions simples qui leur correspondent et qu’elles représentent.<ref>D. Hume, ''A Treatise of Human Nature'', T 1.1.1.7, éd. L. A. Selby‑Bigge, révisée par P. H. Nidditch, Oxford, Oxford University Press, 1978, p. 4.</ref> L’imagination, chez Hume, est la faculté qui manipule ce matériau d’idées. Elle a d’abord un pouvoir mimétique : elle reproduit les impressions sous forme d’idées, en conservant leur contenu qualitatif mais en en diminuant la vivacité. Elle a ensuite un pouvoir productif : elle associe, combine, découpe et recompose ces idées selon des principes d’association (ressemblance, contiguïté dans le temps et l’espace, relation de cause à effet). C’est cette activité associative qui explique que l’esprit passe spontanément d’une idée à une autre, que certaines suites d’idées soient naturelles et d’autres forcées. L’importance de l’imagination chez Hume tient à ce qu’elle intervient dans la genèse de croyances que nous tenons pour évidentes, mais qui, à ses yeux, reposent en réalité sur des « fictions naturelles ». L’idée d’un monde extérieur composé de corps existant de façon continue, par exemple, ne peut pas être directement lue dans l’expérience : elle résulte du travail de l’imagination, qui unifie des perceptions discontinues sous la forme d’une « même chose » persistante. De même, l’idée de nécessité causale n’est pas donnée dans un lien mystérieux entre cause et effet : elle provient de l’habitude qu’a l’imagination de passer, après de nombreuses répétitions, de l’impression de la cause à l’idée de l’effet, puis, peu à peu, de confondre ce passage régulier avec une nécessité objective.<ref>D. Hume, ''A Treatise of Human Nature'', I, IV, 2 ; J. Cottrell, « David Hume : Imagination », ''Internet Encyclopedia of Philosophy'', 2025, en ligne : <nowiki>https://iep.utm.edu/hume-ima/</nowiki>.</ref> Timothy M. Costelloe parle, pour cette raison, de l’imagination comme de la « toile de l’esprit » (''canvas of the mind'') sur laquelle se peignent nos croyances et nos représentations du monde.<ref>T. M. Costelloe, ''The Imagination in Hume’s Philosophy : The Canvas of the Mind'', Édimbourg, Edinburgh University Press, 2018, chap. 1.</ref> Cette toile est à la fois indispensable — sans elle, pas d’unité de l’expérience, pas de science empirique — et suspecte — car ce qu’elle produit n’a pas la nécessité que la raison pourrait souhaiter. L’imagination est ainsi à la fois moteur de la connaissance empirique et source d’illusions philosophiques. === 2.6. Kant : l’imagination transcendantale et la synthèse de l’expérience === Chez Kant, l’imagination acquiert un statut encore plus fondamental. Dans la ''Critique de la raison pure'', Kant cherche les conditions de possibilité de l’expérience objective. Il soutient que toute expérience suppose l’unité d’un multiple sensible, que cette unité ne peut être donnée ni par la sensibilité seule (qui ne fournit que du « manifold ») ni par l’entendement seul (qui ne dispose que de règles formelles). L’imagination (''Einbildungskraft'') est alors définie comme la faculté de « représenter un objet même en son absence », et plus précisément comme la faculté de synthétiser ce multiple selon des règles de l’entendement, afin de produire une expérience unifiée. Dans la ''Déduction transcendantale des catégories'' de l’édition A, Kant distingue trois synthèses : la synthèse d’appréhension dans l’intuition, qui rassemble les données sensibles dans le temps ; la synthèse de reproduction dans l’imagination, qui rappelle, selon des lois d’association, les éléments déjà passés pour maintenir la continuité de la perception ; et la synthèse de reconnaissance dans le concept, par laquelle le sujet identifie ce qu’il aperçoit comme un même objet sous un même concept.<ref>I. Kant, ''Critique de la raison pure'', A98–A110.</ref> L’« imagination transcendantale » est précisément la faculté impliquée dans cette synthèse de reproduction, et plus largement dans l’articulation entre le sensible et l’intelligible. Kant écrit que l’imagination transcendantale est « une fonction de l’âme aveugle, mais indispensable », qui rend possibles les rapports entre la sensibilité et l’entendement.<ref>I. Kant, ''Critique de la raison pure'', A124–A125.</ref> « Aveugle », parce qu’elle ne réfléchit pas explicitement les règles qu’elle applique ; « indispensable », parce que sans elle, les catégories de l’entendement resteraient vides, et les intuitions sensibles privées d’unité. Dans l’édition B, Kant resserre le lien entre imagination et entendement, la présentant davantage comme « fonction de l’entendement appliquée à la sensibilité », ce qui a donné lieu à un vaste débat interprétatif sur la place exacte de l’imagination dans l’architecture de la ''Critique''.<ref>I. Kant, ''Critique de la raison pure'', B151–B152 ; C. McLear, « Two Kinds of Unity in the Critique of Pure Reason », ''Journal of the History of Philosophy'', vol. 49, 2011, p. 79‑110 ; L. U. Tabar, « The Role of Imagination in Kantian Epistemological Theory », ''Tabayyun'', nᵒ 36, 2024.</ref> Dans la ''Critique de la faculté de juger'', l’imagination reçoit une autre fonction, esthétique cette fois. Dans le jugement de goût portant sur le beau, elle entre dans un « libre jeu » harmonieux avec l’entendement : elle déploie des formes, des rapports, des variations que l’entendement trouve « appropriés » sans pouvoir les subsumer sous un concept déterminé. Le plaisir esthétique naît de ce jeu libre, qui fait éprouver au sujet l’accord entre ses facultés sans référence à une finalité déterminée. L’imagination n’est donc plus seulement condition de la connaissance, elle devient condition de possibilité d’un certain type de plaisir désintéressé et de créativité.<ref>I. Kant, ''Critique de la faculté de juger'' (1790), § 9–22, trad. A. Renaut, Paris, GF‑Flammarion, 2000.</ref> === 2.7. Phénoménologie et existentialisme : intentionnalité du fictif === La phénoménologie husserlienne, puis l’existentialisme, donnent à l’imagination une nouvelle profondeur. Husserl traite la ''Phantasie'' comme un mode intentionnel à part entière : imaginer un centaure, par exemple, ce n’est pas simplement « avoir une image » dans l’esprit, c’est viser un objet irréel, absent, selon un mode de donation spécifique (comme « simplement imaginé »). La différence entre perception et imagination n’est pas de contenu (on peut imaginer un cheval aussi précisément qu’on le perçoit), mais de mode d’apparition et de croyance qui y est attachée : la perception prétend donner son objet comme existant, l’imagination ne le fait pas.<ref>E. Husserl, ''Idées directrices pour une phénoménologie'', trad. P. Ricœur, Paris, Gallimard, 1950, § 3–5.</ref> Surtout, Husserl fait de la variation imaginative l’outil central de la réduction eidétique. Pour dégager l’essence d’un phénomène (par exemple, ce que c’est qu’une table, un acte de promesse, une perception), le phénoménologue varie en imagination ses traits : il imagine des tables de bois, de métal, suspendues au plafond, miniatures, gigantesques, et cherche ce qui peut changer sans que la chose cesse d’être une table, et ce qui ne peut pas changer sans la détruire en tant que telle. L’imagination devient ainsi, non un domaine de fantaisie arbitraire, mais un instrument rigoureux pour accéder aux structures nécessaires de l’expérience.<ref>Ch.-Y. Lee, « Reconsidering Husserl’s Method of Eidetic Variation », ''Husserl Studies'', vol. 39, 2023, p. 1‑26.</ref> Jean‑Paul Sartre reprend ces analyses dans un registre existentiel. Dans ''L’Imagination'' puis ''L’Imaginaire'', il critique ce qu’il appelle la « métaphysique naïve de l’image », selon laquelle il y aurait, dans l’esprit, de petites images‑objets que la conscience regarderait comme un spectateur. Pour Sartre, imaginer Pierre, c’est structurer la conscience elle‑même comme visée d’un objet absent : la conscience « néantise » le monde présent pour faire place à ce qui n’est pas là. L’imagination manifeste ainsi le pouvoir de la conscience de se détacher du donné, de se rapporter à l’irréel, d’ouvrir un espace de possibles où la liberté humaine peut se déployer — mais aussi se perdre, en se réfugiant dans des fuites imaginaires.<ref>J.-P. Sartre, ''L’Imagination'' (1936), Paris, PUF, 2005 ; ''L’Imaginaire. Psychologie phénoménologique de l’imagination'' (1940), Paris, Gallimard, 1948.</ref> === 2.8. Perspectives contemporaines : architecture cognitive et usages multiples === Les recherches contemporaines, à l’intersection de la philosophie de l’esprit, de l’esthétique, de l’épistémologie et des sciences cognitives, multiplient les analyses de l’imagination. En philosophie de l’esprit, on s’intéresse à sa structure cognitive : comment se relie‑t‑elle à la mémoire, à la perception, à la supposition (« supposons que… »), à la croyance, à la simulation motrice ? Gregory Currie et Ian Ravenscroft proposent de comprendre l’imagination comme une capacité « recréative » : elle reproduit, de façon « débranchée », le fonctionnement d’autres états mentaux (croyances, perceptions, émotions) dans des « boucles » simulées qui ne débouchent pas sur l’action réelle.<ref>G. Currie et I. Ravenscroft, ''Recreative Minds. Imagination in Philosophy and Psychology'', Oxford, Oxford University Press, 2002.</ref> En esthétique, on analyse la manière dont les œuvres de fiction sollicitent l’imagination du lecteur ou du spectateur. Comment un simple texte peut‑il susciter des images riches ? Comment expliquer le « paradoxe de la fiction » : le fait que nous éprouvions de véritables émotions pour des personnages que nous savons inexistants ? Une réponse classique, inspirée notamment par Kendall Walton, consiste à dire que nous faisons « comme si » les personnages étaient réels : nous participons à un jeu de ''make‑believe'' qui met notre imagination au premier plan.<ref>K. Walton, ''Mimesis as Make‑Believe. On the Foundations of the Representational Arts'', Cambridge (Mass.), Harvard University Press, 1990.</ref> En épistémologie, on s’interroge sur les valeurs et les limites de l’imagination comme guide vers la possibilité. Dans la théorie des mondes possibles, on a souvent soutenu que ce que l’on peut concevoir ou imaginer sans contradiction donne un bon indice de ce qui est réellement possible, même dans des domaines abstraits comme la métaphysique ou les mathématiques. D’autres, au contraire, soulignent la fragilité d’un tel critère : il est très facile d’imaginer des scénarios logiquement impossibles sans s’en rendre compte, et très difficile d’imaginer certains scénarios pourtant possibles, parce qu’ils heurtent nos habitudes conceptuelles ou nos limites cognitives. Des travaux récents, réunis par Amy Kind et Peter Kung, essaient de préciser dans quelles conditions l’imagination peut être une source de connaissance ou de justification épistémique, et dans quelles limites elle doit rester un simple outil heuristique.<ref>A. Kind et P. Kung (dir.), ''Knowledge Through Imagination'', Oxford, Oxford University Press, 2016.</ref> Enfin, en éthique, on examine le rôle du « sens moral » imaginatif : la capacité de se projeter dans la situation d’autrui, d’anticiper les effets de ses actions, d’élargir son horizon à des vies très différentes de la sienne. Mais l’on souligne aussi les risques d’un imaginaire nourrissant des fantasmes violents, racistes ou sexistes. Shen‑Yi Liao et Adina Strohminger, par exemple, montrent comment l’imagination peut servir de laboratoire moral, mais aussi comment certains contenus imaginés peuvent révéler ou renforcer des traits problématiques de notre caractère.<ref>S.-Y. Liao et A. Strohminger, « Ethics and Imagination », dans A. Kind (dir.), ''The Routledge Handbook of Philosophy of Imagination'', New York, Routledge, 2016, p. 425‑439.</ref> == 3. Fonctions de l’imagination == === 3.1. Explorer le possible : planification, décision, science === Une fonction évidente de l’imagination est d’ouvrir un espace de possibles au‑delà du présent et du réel. John Dewey insiste sur ce point dans sa philosophie morale. Pour lui, délibérer moralement, ce n’est pas appliquer machinalement une règle, c’est mettre en scène, en imagination, différentes lignes d’action, et jouer mentalement leurs conséquences avant d’agir. Un acte effectivement accompli est irrévocable ; un acte « essayé en imagination » peut être modifié, abandonné, révisé, sans dommage. La délibération est donc une sorte de « drame intérieur » où l’imagination permet de tester des actions possibles et de voir, de l’intérieur, ce qu’elles feraient à soi et aux autres.<ref>J. Dewey, ''Human Nature and Conduct : An Introduction to Social Psychology'' (1922), New York, Holt, 1922, 2ᵉ partie, chap. 14‑15 ; édition en ligne : <nowiki>https://www.gutenberg.org/files/41386/41386-h/41386-h.htm</nowiki>.</ref> Concrètement, dans la vie quotidienne, l’imagination nous permet d’anticiper les effets d’une parole blessante ou bienveillante, d’une prise de risque, d’un mensonge. Dans le domaine technique, elle sert à simuler mentalement la trajectoire d’un projectile, la robustesse d’une structure, le fonctionnement d’une machine. Dans la science, elle est omniprésente : formuler une hypothèse, c’est déjà imaginer un état possible du monde ; concevoir une expérience de pensée, c’est construire un scénario souvent irréalisable dans l’immédiat, mais cohérent avec une théorie donnée, afin d’en explorer les conséquences. Les expériences de pensée scientifiques classiques (le train d’Einstein illustrant la relativité, l’ascenseur d’Einstein, le chat de Schrödinger, etc.) montrent comment l’imagination travaille au cœur des théories. Elle ne s’autorise pas n’importe quoi : elle respecte les lois supposées en vigueur dans le cadre conceptuel adopté, tout en les plaçant dans des situations extrêmes ou inédites. Elle joue ainsi un rôle heuristique et critique : elle permet de tester la cohérence interne d’une théorie, de dévoiler des conséquences inattendues, voire de mettre en lumière des tensions qui exigeront une révision conceptuelle.<ref>A. Miščević, « Mental Models and Thought Experiments », ''International Studies in the Philosophy of Science'', vol. 6, 1992, p. 215‑226 ; A. Cooper, « Expérience de pensée (A) », ''L’Encyclopédie philosophique'', 2014, en ligne : <nowiki>https://encyclo-philo.fr/experiences-de-pensee-a/</nowiki>.</ref> === 3.2. Art, fiction et empathie === Dans le domaine esthétique, l’imagination joue un rôle double, du côté de la création comme de la réception. L’artiste – écrivain, cinéaste, peintre, compositeur – invente des mondes, des personnages, des paysages sonores ou visuels, en puisant dans son expérience, mais aussi en la transgressant. Son imagination ne se contente pas d’imiter : elle reconfigure des éléments connus dans des combinaisons nouvelles, parfois surprenantes, parfois inquiétantes. Les œuvres de fiction, en particulier, proposent au lecteur ou au spectateur des situations, des psychologies, des univers qu’il n’a jamais rencontrés. Du côté du récepteur, l’imagination est tout aussi sollicitée. Un roman ne fournit que des lignes d’encre ; c’est le lecteur qui, à partir de quelques indications, reconstruit des visages, des lieux, des ambiances, et suit en imagination l’enchaînement des actions. Un film, même très réaliste, exige aussi une part d’imagination : les ellipses, les hors‑champ, les non‑dits invitent le spectateur à compléter. Dans la musique instrumentale, l’imagination est peut‑être encore plus libre : elle associe aux motifs sonores des images, des sentiments, des histoires qui ne sont pas explicitement racontées. C’est également par l’imagination que l’on comprend les émotions suscitées par la fiction. Nous savons que les personnages que nous voyons souffrir ou triompher n’existent pas réellement, et pourtant nous éprouvons de la peur, de la compassion, de la joie, de la honte à leur sujet. Une manière de résoudre ce « paradoxe de la fiction », proposée notamment par Kendall Walton, consiste à dire que nous jouons au « faire comme si » : nous faisons comme si ces personnages étaient réels, et dans le cadre de ce jeu, les émotions sont pleinement investies, même si, en arrière‑plan, nous gardons la conscience de la fictionnalité de la situation.<ref>N. Carroll, ''The Philosophy of Horror, or Paradoxes of the Heart'', New York, Routledge, 1990 ; K. Walton, ''Mimesis as Make‑Believe'', op. cit.</ref> Enfin, l’imagination est au cœur de l’empathie. Se mettre à la place d’autrui, ce n’est pas seulement appliquer une règle morale abstraite, c’est se représenter, de façon vivante, ce que l’autre ressent ou ressentirait dans telle situation. Alvin Goldman et d’autres théoriciens de la « simulation » soutiennent que nous comprenons souvent les intentions et les émotions d’autrui en « jouant en nous‑mêmes » son rôle : nous activons, en imagination, des états mentaux et corporels analogues aux siens, ce qui nous permet de les saisir de l’intérieur.<ref>A. I. Goldman, ''Simulating Minds. The Philosophy, Psychology, and Neuroscience of Mindreading'', Oxford, Oxford University Press, 2006.</ref> L’imagination devient alors un outil de compréhension intersubjective, mais aussi, potentiellement, une école de sensibilité morale. === 3.3. Morale, politique et imaginaire social === L’imagination intervient également de manière décisive dans la vie morale et politique. On parle parfois de « raison pratique imaginaire » pour désigner la capacité de se projeter dans des situations auxquelles on n’a jamais été confronté, de prendre en compte le point de vue des autres, d’anticiper des effets lointains de ses choix. Avant de décider, un agent moral peut, par exemple, imaginer comment une parole humiliante sera reçue par son interlocuteur, quelle blessure elle risque de creuser, comment elle pourrait être ressentie des années plus tard. Cette projection imaginative ne remplace pas le raisonnement ni la connaissance des faits, mais elle leur donne chair et densité. À l’échelle collective, l’imagination nourrit ce que certains appellent l’« imaginaire social ». Une société se représente son passé, son avenir, ses héros, ses ennemis, ses valeurs à travers des récits, des images, des symboles. Ces constructions imaginaires ne sont pas purement arbitraires : elles sédimentent des expériences historiques, des conflits, des aspirations. Elles peuvent ouvrir l’espace de formes de vie alternatives (utopies politiques, projets de réforme, mouvements sociaux) ou, au contraire, enfermer un groupe dans des stéréotypes et des peurs. L’imagination collective est à la fois moteur d’émancipation et ressort de l’idéologie. Dans la philosophie morale contemporaine, des auteurs comme Shen‑Yi Liao et Adina Strohminger ont attiré l’attention sur la dimension proprement morale de certains usages de l’imagination.<ref>S.-Y. Liao et A. Strohminger, art. cit., p. 425‑439.</ref> Imaginer, par jeu, des scènes de violence ou d’humiliation n’est pas en soi un crime ; mais si ces scénarios deviennent répétitifs, complaisants, peuplés de personnages stéréotypés, ils peuvent à la fois révéler et renforcer des dispositions morales problématiques. À l’inverse, cultiver une imagination attentive à la diversité des expériences humaines, capable d’habiter en pensée des points de vue très éloignés du sien, peut être vu comme une forme de vertu. L’imagination ne se contente pas d’illustrer nos valeurs : elle contribue à les former ou à les déformer. == 4. Problèmes philosophiques centraux == === 4.1. Imagination et vérité : source de connaissance ou d’illusion ? === Depuis Platon, une tension traverse la réflexion sur l’imagination : est‑elle une faculté intrinsèquement suspecte, parce qu’elle se situe du côté du « semblant » et du « comme si », ou bien une source potentielle de connaissance, notamment dans l’exploration des possibles ? Platon, on l’a vu, tend vers la méfiance : l’imagination est au bas de l’échelle cognitive. Malebranche, au XVIIᵉ siècle, parle de l’imagination comme de « la folle du logis », expression devenue célèbre, pour désigner la facilité avec laquelle elle nous fait prendre des chimères pour des réalités et nous détourne de l’attention pure à l’objet intelligible.<ref>N. Malebranche, ''De la recherche de la vérité'', III, 2, Paris, Vrin, 1979.</ref> Pascal, dans les ''Pensées'', consacre une section très sévère à « cette maîtresse d’erreur et de fausseté » qu’est l’imagination, capable de donner prestige à l’injustice, autorité à la coutume la plus arbitraire, et de nous aveugler sur notre propre misère.<ref>B. Pascal, ''Pensées'', éd. L. Brunschvicg, Paris, Hachette, 1897, fr. 82 (« Imagination »).</ref> D’un autre côté, la réhabilitation kantienne et phénoménologique de l’imagination montre combien elle est indispensable à la connaissance. Sans elle, pas de synthèse du multiple sensible, pas de possibilité d’identifier un même objet au fil du temps, pas d’unité de l’expérience. Sans elle, pas de variation eidétique permettant de dégager les structures nécessaires d’un phénomène. Les sciences cognitives contemporaines renforcent ce constat : l’imagination est au cœur de processus comme la simulation mentale de trajectoires physiques, la planification d’actions, l’apprentissage par essais et erreurs, y compris « en interne ». Les débats récents en épistémologie portent précisément sur la question de savoir si l’imagination peut, dans certains cas, être une véritable source de justification épistémique. Des auteurs comme Amy Kind défendent l’idée que, lorsqu’un sujet utilise de manière compétente son imagination dans un environnement familier, il peut en tirer des croyances fiables : par exemple, imaginer la valise dans le compartiment d’avion pour juger si elle y rentrera, ou imaginer le fonctionnement d’un circuit simple pour anticiper sa défaillance.<ref>A. Kind et P. Kung (dir.), ''Knowledge Through Imagination'', op. cit.</ref> D’autres, plus sceptiques, comme certains critiques de cette position, soutiennent que la véritable source de justification réside dans les connaissances et les règles déjà acquises, l’imagination ne servant qu’à rendre ces connaissances plus accessibles ou plus saillantes, sans ajouter par elle‑même de nouveaux fondements. L’imagination aurait alors un rôle heuristique et pragmatique important, mais non un rôle fondationnel dans la structure de nos raisons. Une partie du désaccord tient à la diversité des cas étudiés. Dans des tâches simples de géométrie ou de mécanique, l’imagination semble relativement fiable. Dans des spéculations métaphysiques (sur les mondes possibles, la nature de l’esprit, l’architecture de l’espace‑temps), elle paraît beaucoup plus incertaine. Il est probable que le statut épistémique de l’imagination ne soit pas uniforme : tout dépend des domaines, des compétences du sujet, des contrôles qu’il met en place pour limiter ses propres biais. === 4.2. Volonté et spontanéité === L’impression de contrôle volontaire que nous avons souvent sur notre imagination mérite aussi un examen critique. À première vue, il semble que nous puissions décider librement de ce que nous imaginons : si l’on nous demande d’imaginer un chat sur la table, nous y parvenons immédiatement ; si l’on veut explorer une possibilité pratique, comme un déménagement ou un changement de métier, on peut se concentrer et « faire défiler » des scénarios. Cette disponibilité contraste avec la résistance de la croyance : on ne choisit pas, en général, de croire à volonté une proposition que l’on juge fausse. Mais cette apparente maîtrise se fissure dès que l’on regarde les choses de plus près. D’une part, il existe des contenus imaginaires que l’on préférerait ne pas avoir, et qui s’imposent pourtant avec force : souvenirs traumatiques, images intrusives dans certains troubles obsessionnels, ruminations répétitives. L’imagination peut alors devenir envahissante, voire pathologique, et se soustraire au contrôle conscient. D’autre part, même lorsque l’on dirige volontairement son imagination, ce que l’on parvient effectivement à imaginer est soumis à des contraintes structurelles : des habitudes d’association, des schèmes narratifs, des stéréotypes peuvent limiter l’éventail des scénarios envisagés. Il ne suffit pas de vouloir imaginer une société radicalement différente de la nôtre pour y parvenir en détail. C’est pourquoi certains auteurs parlent d’un « contrôle partiel » de l’imagination : elle est, dans une certaine mesure, commandable et modulable, plus que ne le sont la perception et la croyance, mais elle obéit aussi à des dynamiques propres.<ref>A. Kind, ''Imagination and Creative Thinking'', Cambridge, Cambridge University Press, 2022, chap. 2.</ref> On peut toutefois la travailler comme une compétence : apprendre à varier les points de vue, à déjouer les automatismes, à explorer systématiquement des cas marginaux. L’imagination, en ce sens, n’est pas seulement un don naturel, mais aussi un art qui s’apprend. === 4.3. Imagination, croyance et « mise en quarantaine » === La relation entre imagination et croyance est un autre point de tension. D’un côté, la thèse de la « mise en quarantaine » insiste sur le fait qu’imaginer n’est pas croire. Imaginer que la pièce est en feu ne conduit pas, normalement, à se précipiter vers la sortie : le sujet sait qu’il joue un rôle, ou qu’il explore une hypothèse, et ne transforme pas ce contenu en croyance sur l’état réel du monde. Tamar Gendler montre cependant que cette frontière est plus poreuse qu’on ne le croit : des contenus imaginés peuvent influencer nos émotions, et ces émotions peuvent, à leur tour, infléchir nos croyances et nos attitudes.<ref>T. S. Gendler, ''Intuition, Imagination, and Philosophical Methodology'', op. cit., chap. 5.</ref> De plus, il arrive qu’un contenu d’abord seulement imaginé se transforme en croyance par répétition, par confusion de sources ou par absence de vigilance critique. Des rumeurs peuvent ainsi naître de scénarios fictionnels pris au sérieux, des théories complotistes peuvent se cristalliser à partir de « supposons que… » qui n’auraient jamais dû sortir du registre hypothétique. Inversement, certaines croyances peuvent rester à demi « fictionnalisées » : un sujet peut, par exemple, affirmer croire en une norme morale ou en un idéal politique, mais ne jamais en tirer les conséquences pratiques, comme si cette croyance restait confinée dans un compartiment imaginaire de sa vie psychique. Ces interactions complexes entre imagination et croyance intéressent autant les philosophes que les psychologues cliniciens. Elles permettent d’éclairer la frontière entre la fiction et le délire, entre le jeu de rôle assumé et la confusion pathologique des niveaux de réalité. Elles posent aussi des questions éthiques et politiques : à quel moment un « jeu » imaginatif devient‑il un ferment de radicalisation, ou un instrument de manipulation collective ? === 4.4. Imagination et subjectivité === Enfin, l’imagination est intimement liée à la subjectivité. Elle rend possible la projection de soi dans d’autres situations, d’autres temporalités, d’autres identités. On peut se représenter sa vie dans dix ans, rejouer un événement passé en explorant ce qui se serait passé si l’on avait fait un autre choix, s’imaginer dans un autre corps, un autre genre, une autre position sociale. Ces exercices ne sont pas de simples distractions : ils participent à l’élaboration de ce que chacun se raconte sur lui‑même. Les récits de soi mobilisent constamment l’imagination : ils recomposent le passé, sélectionnent certains épisodes, en valorisent d’autres, esquissent des futurs possibles. Husserl, avec la méthode de la variation eidétique, montre comment l’on peut, en modifiant imaginativement certains traits de son propre vécu, chercher ce qui est essentiel à son identité et ce qui, au contraire, pourrait être autrement sans que l’on cesse d’être soi.<ref>E. Husserl, ''Méditations cartésiennes'', trad. G. Peiffer, Paris, Vrin, 2004, Vᵉ méditation.</ref> Sartre, de son côté, insiste sur le fait que l’homme ne se réduit jamais à ce qu’il est effectivement : par l’imagination, il se dépasse vers des possibles qui ne sont pas encore, ce qui constitue à la fois la grandeur de la liberté et la tentation de la mauvaise foi, lorsque l’on se cache derrière des « je pourrais bien un jour » pour ne pas assumer ce que l’on est en acte. De ce point de vue, travailler son imagination, ce n’est pas seulement cultiver une faculté esthétique : c’est aussi prendre en main, au moins partiellement, la manière dont on se comprend soi‑même et dont on se projette dans l’avenir. == 5. Synthèse : une faculté ambivalente et structurante == L’histoire philosophique de l’imagination fait apparaître une oscillation constante. D’un côté, l’imagination est suspecte : elle s’attache aux apparences, nourrit l’illusion, excite les passions, détourne de la vérité. De l’autre, elle apparaît comme une condition de possibilité de l’expérience unifiée, de la recherche scientifique, de la création artistique et de la compréhension morale. Elle se situe à la frontière entre le réel et le possible, entre le donné et le concevable, entre l’ici‑et‑maintenant et l’« ailleurs ». Les conceptions contemporaines invitent à la penser moins comme une « faculté » isolée que comme un nœud de fonctions : elle relie la perception, la mémoire et l’anticipation ; elle soutient la construction de modèles mentaux dans lesquels nous testons des actions ; elle rend possible la fiction littéraire, cinématographique, théâtrale ; elle permet l’empathie, la projection dans la vie d’autrui, mais aussi la construction d’imaginaires politiques et sociaux puissants, pour le meilleur et pour le pire. Sur le plan cognitif, l’imagination assure la liaison entre ce que nous percevons effectivement et ce que nous pensons pouvoir arriver : elle est au cœur du raisonnement contrefactuel (« si j’avais fait ceci… », « si la loi de la gravitation était différente… »), de la construction de mondes possibles et de l’apprentissage par essais et erreurs mentaux. Sur le plan pratique, elle ouvre l’espace des fins et des moyens possibles : sans elle, nous serions prisonniers du présent, incapables de nous orienter vers un avenir un peu complexe. Sur le plan esthétique, elle est à la fois l’outil du créateur et la voie d’accès du récepteur aux œuvres. Sur le plan moral et politique, elle est la condition d’un élargissement du point de vue, mais aussi le terrain d’où peuvent surgir des fantasmes dangereux et des fictions collectives aliénantes. Plutôt que de chercher à « dompter » l’imagination en la réduisant ou en la suspectant en bloc, la philosophie contemporaine tend donc à en analyser les structures fines, les conditions de fiabilité et les déformations typiques. Il s’agit de comprendre comment ce pouvoir de simulation, si essentiel à notre humanité, peut à la fois éclairer le réel et nous en détourner. Cette démarche suppose de tenir ensemble les deux visages de l’imagination : celui, lumineux, de l’ouverture au possible, de la créativité, de l’empathie ; et celui, plus sombre, de l’illusion, du fantasme et de la manipulation. C’est à cette condition que l’on peut espérer faire de l’imagination, non une ennemie de la raison, mais une alliée lucide, à la fois libre et instruite. == Références == {{references}} == Bibliographie == === Textes classiques === * Aristote, ''De anima'', trad. R. Bodéüs, Paris, GF‑Flammarion, 1995. * Descartes, René, ''Méditations métaphysiques'', dans ''Œuvres philosophiques'', t. II, éd. F. Alquié, Paris, Garnier, 1967. * Dewey, John, ''Human Nature and Conduct : An Introduction to Social Psychology'', New York, Holt, 1922 (texte en ligne : Project Gutenberg). * Hume, David, ''A Treatise of Human Nature'' (1739‑1740), éd. L. A. Selby‑Bigge, révisée par P. H. Nidditch, Oxford, Oxford University Press, 1978. * Husserl, Edmund, ''Idées directrices pour une phénoménologie'', trad. P. Ricœur, Paris, Gallimard, 1950. * Husserl, Edmund, ''Méditations cartésiennes'', trad. G. Peiffer, Paris, Vrin, 2004. * Kant, Immanuel, ''Critique de la raison pure'', trad. A. Tremesaygues et B. Pacaud, Paris, PUF, 1987. * Kant, Immanuel, ''Critique de la faculté de juger'', trad. A. Renaut, Paris, GF‑Flammarion, 2000. * Malebranche, Nicolas, ''De la recherche de la vérité'', éd. G. Rodis‑Lewis, Paris, Vrin, 1979. * Pascal, Blaise, ''Pensées'', éd. L. Brunschvicg, Paris, Hachette, 1897. * Platon, ''La République'', trad. G. Leroux, Paris, GF‑Flammarion, 2002. * Sartre, Jean‑Paul, ''L’Imagination'' (1936), Paris, PUF, 2005. * Sartre, Jean‑Paul, ''L’Imaginaire. Psychologie phénoménologique de l’imagination'' (1940), Paris, Gallimard, 1948. * Thomas d’Aquin, ''Somme de théologie'', Iᵉʳ volume, trad. J.-P. Torrell, Paris, Cerf, 1999. === Études et ouvrages contemporains === * Carroll, Noël, ''The Philosophy of Horror, or Paradoxes of the Heart'', New York, Routledge, 1990. * Cooper, Anthony, « Expérience de pensée (A) », ''L’Encyclopédie philosophique'', 2014 : <nowiki>https://encyclo-philo.fr/experiences-de-pensee-a/</nowiki>. * Costelloe, Timothy M., ''The Imagination in Hume’s Philosophy : The Canvas of the Mind'', Édimbourg, Edinburgh University Press, 2018. * Currie, Gregory et Ravenscroft, Ian, ''Recreative Minds. Imagination in Philosophy and Psychology'', Oxford, Oxford University Press, 2002. * Gendler, Tamar Szabó, ''Intuition, Imagination, and Philosophical Methodology'', Oxford, Oxford University Press, 2010. * Goldman, Alvin I., ''Simulating Minds. The Philosophy, Psychology, and Neuroscience of Mindreading'', Oxford, Oxford University Press, 2006. * Kind, Amy, ''Imagination and Creative Thinking'', Cambridge, Cambridge University Press, 2022. * Kind, Amy et Kung, Peter (dir.), ''Knowledge Through Imagination'', Oxford, Oxford University Press, 2016. * Liao, Shen‑Yi et Gendler, Tamar Szabó, « Imagination », ''Stanford Encyclopedia of Philosophy'', <nowiki>https://plato.stanford.edu/entries/imagination/</nowiki>. * Liao, Shen‑Yi et Strohminger, Adina, « Ethics and Imagination », dans A. Kind (dir.), ''The Routledge Handbook of Philosophy of Imagination'', New York, Routledge, 2016, p. 425‑439. * Miščević, Nenad, « Mental Models and Thought Experiments », ''International Studies in the Philosophy of Science'', vol. 6, 1992, p. 215‑226. * Saint-Germier, Pierre, « Imagination (GP) », ''L’Encyclopédie philosophique'', <nowiki>https://encyclo-philo.fr/imagination-gp/</nowiki>. * Walton, Kendall, ''Mimesis as Make‑Believe. On the Foundations of the Representational Arts'', Cambridge (Mass.), Harvard University Press, 1990. * Cottrell, Jonathan, « David Hume : Imagination », ''Internet Encyclopedia of Philosophy'', <nowiki>https://iep.utm.edu/hume-ima/</nowiki>. * Lee, Chin‑Yu, « Reconsidering Husserl’s Method of Eidetic Variation », ''Husserl Studies'', vol. 39, 2023, p. 1‑26. {{Autocat}} pk9xa0phsces8v6qjbgf9f2ynsla0dc Dictionnaire de philosophie/N 0 83950 768454 767977 2026-06-24T02:28:25Z PandaMystique 119061 768454 wikitext text/x-wiki {{DicoPhilo|N}} <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 2em; width: 100%; margin-bottom: 2em;"> <div style="padding: 1.5em; background: linear-gradient(135deg, #ffffff40 0%, #e0e4e840 100%); border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.1);"> :[[Dictionnaire de philosophie/Thomas Nagel|Nagel, Thomas]] :Nation :Nature :Néant :Nécessité :Négation :Négativité :Néokantisme :Néoplatonisme </div> <div style="padding: 1.5em; background: linear-gradient(135deg, #ffffff40 0%, #e0e4e840 100%); border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.1);"> :Néostoïcisme :Nihilisme :Noème :Noèse :Nom :Nombre :Nominalisme :Non-contradiction </div> <div style="padding: 1.5em; background: linear-gradient(135deg, #ffffff40 0%, #e0e4e840 100%); border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.1);"> :Non-être :Non-violence :Normal :Normativité :Norme :Notion :Noumène </div> </div> {{PhiloRecherche}} {{autocat}} 1pgyyo2uhhy5o55dajq9gnahplym7y4 Fonctionnement d'un ordinateur/Les circuits incrémenteurs/décrémenteurs 0 83953 768402 768202 2026-06-23T14:18:28Z Mewtow 31375 /* Les incrémenteurs carry skip */ 768402 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> dbjckk2ab36ta59dx61ll2zr1dhkpqi 768403 768402 2026-06-23T14:33:23Z Mewtow 31375 /* Les incrémenteurs carry skip */ 768403 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. Par contre, en inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. La retenue n'a plus qu'à traverser deux portes logiques. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> op2nhrwa5utgkkluk7445nroyts6qjx 768404 768403 2026-06-23T14:35:00Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768404 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. Par contre, en inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. La retenue n'a plus qu'à traverser deux portes logiques. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 4nxtpxrh9adbqm6zu2dsq4uylxroz99 768405 768404 2026-06-23T14:35:25Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768405 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. Par contre, en inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. La retenue n'a plus qu'à traverser deux portes logiques. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> te35yj3sgxerdc57pkj7zhjt4cpsvdl 768406 768405 2026-06-23T14:42:32Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768406 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] La retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 9397y0x1sijojt975dt10g1pkhnr5e8 768407 768406 2026-06-23T14:43:22Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768407 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler ici. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 0ckihi4fl8wpeko8wj823mj2s8m8gj4 768408 768407 2026-06-23T14:44:49Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768408 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 2xb8lztvgegy81crio4yuxcy9niif4g 768409 768408 2026-06-23T15:00:19Z Mewtow 31375 /* Le demi-additionneur */ 768409 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il est possible de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Ci-dessous, vous aurez deux implémentations possibles. Attention cependant, l'implémentation avec les portes NOR demande d'ajouter deux portes NON, non-représentées, pour calculer l'inverse des deux bits d'entrée. Pour l'implémentation avec des portes NAND, le demi-additionneur fournit non pas la retenue adéquate, mais l'inverse de la retenue. Et ce détail sera utile ci-dessous. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> gyk4uo4mca3lv9lxx6gfzdeo1q1pf9h 768410 768409 2026-06-23T15:16:45Z Mewtow 31375 /* Le demi-additionneur */ 768410 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il est possible de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Ci-dessous, vous aurez deux implémentations possibles. Attention cependant, l'implémentation avec les portes NOR mixe les deux bits d'entrée et leurs inverses. Obtenir un demi-additionneur classique demande d'ajouter deux portes NON, non-représentées, pour calculer l'inverse des deux bits d'entrée. Pour l'implémentation avec des portes NAND, le demi-additionneur fournit non pas la retenue adéquate, mais l'inverse de la retenue. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ou au contraire l'inverse des entrées, mais ce détail sera utile ci-dessous. En effet, ces deux implémentations sont utilisées pour simplifier les circuits incrémenteurs et les rendre plus rapides. ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi. , et aucun des deux ne ressemble à un demi-additionneur normal. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 16kz6a1aacrvbcq4tfnj9z8krr3g66m 768411 768410 2026-06-23T15:18:13Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768411 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il est possible de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Ci-dessous, vous aurez deux implémentations possibles. Attention cependant, l'implémentation avec les portes NOR mixe les deux bits d'entrée et leurs inverses. Obtenir un demi-additionneur classique demande d'ajouter deux portes NON, non-représentées, pour calculer l'inverse des deux bits d'entrée. Pour l'implémentation avec des portes NAND, le demi-additionneur fournit non pas la retenue adéquate, mais l'inverse de la retenue. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ou au contraire l'inverse des entrées, mais ce détail sera utile ci-dessous. En effet, ces deux implémentations sont utilisées pour simplifier les circuits incrémenteurs et les rendre plus rapides. ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 4rhrv4thq6tcyk464z7u49tlvgvua5k 768412 768411 2026-06-23T15:28:55Z Mewtow 31375 /* Le demi-additionneur */ 768412 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. En supprimant ces redondances, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. Il est possible de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Ci-dessous, vous aurez deux implémentations possibles. Attention cependant, l'implémentation avec les portes NOR mixe les deux bits d'entrée et leurs inverses. Obtenir un demi-additionneur classique demande d'ajouter deux portes NON, non-représentées, pour calculer l'inverse des deux bits d'entrée. Pour l'implémentation avec des portes NAND, le demi-additionneur fournit non pas la retenue adéquate, mais l'inverse de la retenue. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ou au contraire l'inverse des entrées, mais ce détail sera utile ci-dessous. En effet, ces deux implémentations sont utilisées pour simplifier les circuits incrémenteurs et les rendre plus rapides. ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 6nyb4251ngi6olovz84k8u8bmnhx14q 768413 768412 2026-06-23T15:35:59Z Mewtow 31375 /* Le demi-additionneur */ 768413 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Il est possible d'aller plus loin et de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Ci-dessous, vous aurez deux implémentations possibles. Attention cependant, l'implémentation avec les portes NOR mixe les deux bits d'entrée et leurs inverses. Obtenir un demi-additionneur classique demande d'ajouter deux portes NON, non-représentées, pour calculer l'inverse des deux bits d'entrée. Pour l'implémentation avec des portes NAND, le demi-additionneur fournit non pas la retenue adéquate, mais l'inverse de la retenue. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ou au contraire l'inverse des entrées, mais ce détail sera utile ci-dessous. En effet, ces deux implémentations sont utilisées pour simplifier les circuits incrémenteurs et les rendre plus rapides. ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> fw32ifp49igkxjzw0ha56ezwm6nz13p 768414 768413 2026-06-23T15:41:45Z Mewtow 31375 /* Le demi-additionneur */ 768414 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Il est possible de faire la même chose, en utilisant des portes NAND, au lieu des portes NOR. Et avec cette implémentation, le bit de somme est calculée à partir de la retenue. Attention cependant : le circuit illustré ci-dessous utilise non pas la retenue du résultat, mais son inverse. Pour obtenir la retenue en sortie, il faut utiliser une porte NON. Cependant, nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs. Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ce demi-additionneur est utilisé pour rendre plus rapide le calcul des retenues. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] Il est possible d'aller plus loin et de créer des demi-additionneurs avec uniquement des portes NOR et NAND. Mais ce n'est qu'un détail que je mentionnes par souci d'exhaustivité. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 1dfkgwg9whbaoebbv71u60btjylfm8j 768415 768414 2026-06-23T15:42:08Z Mewtow 31375 /* Le demi-additionneur */ 768415 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Il est possible de faire la même chose, en utilisant des portes NAND, au lieu des portes NOR. Et avec cette implémentation, le bit de somme est calculée à partir de la retenue. Attention cependant : le circuit illustré ci-dessous utilise non pas la retenue du résultat, mais son inverse. Pour obtenir la retenue en sortie, il faut utiliser une porte NON. Cependant, nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs. Il peut sembler étrange de créer des circuits qui fournissent l'inverse du bit de retenue, ce demi-additionneur est utilisé pour rendre plus rapide le calcul des retenues. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 3r0yjim16tlbtt3olzdudif3r9onbva 768416 768415 2026-06-23T15:46:03Z Mewtow 31375 /* Le demi-additionneur */ 768416 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Une implémentation alternative utilise des portes NAND. Pour rappel, il est possible de créer une porte XOR avec 4 portes NAND. La première d'entre elle fait un NAND entre les deux bits d'entrée, ce qui fait qu'elle calcule l'inverse de la retenue sortante. Le tout est illustré ci-dessous. En théorie, on devrait utiliser une porte NON pour récupérer la retenue correcte. Mais nous verrons plus bas que ce n'est pas une obligation. Nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs, pour rendre les calculs plus rapides. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> m8g8rzx45vfsy4urmk8nawqmsz93kzs 768418 768416 2026-06-23T15:49:19Z Mewtow 31375 /* Le demi-additionneur */ 768418 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Une implémentation alternative utilise des portes NAND. Pour rappel, il est possible de créer une porte XOR avec 4 portes NAND. La première d'entre elle fait un NAND entre les deux bits d'entrée, ce qui fait qu'elle calcule l'inverse de la retenue sortante. Le tout est illustré ci-dessous. En théorie, on devrait utiliser une porte NON pour récupérer la retenue correcte. Mais nous verrons plus bas que ce n'est pas une obligation. Nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs, pour rendre les calculs plus rapides. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] Il est aussi possible d'implémenter un demi-additionneur avec uniquement des portes NOR et NAND. [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> 15wq18d00rhtpebj38tyyed3x4edpll 768452 768418 2026-06-23T19:53:43Z Mewtow 31375 /* Le demi-additionneur */ 768452 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Une implémentation alternative, qui n'utilise que des portes NOR, est la suivante : [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Une implémentation alternative utilise des portes NAND. Pour rappel, il est possible de créer une porte XOR avec 4 portes NAND. La première d'entre elle fait un NAND entre les deux bits d'entrée, ce qui fait qu'elle calcule l'inverse de la retenue sortante. Le tout est illustré ci-dessous. En théorie, on devrait utiliser une porte NON pour récupérer la retenue correcte. Mais nous verrons plus bas que ce n'est pas une obligation. Nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs, pour rendre les calculs plus rapides. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> c4ffxl4ufv86dqmhw89jqusn89k4u5t 768453 768452 2026-06-23T19:54:36Z Mewtow 31375 /* Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel */ 768453 wikitext text/x-wiki Le circuit '''incrémenteur''' incrémente un nombre entier. Plus précisément, il prend en entrée un nombre entier, et fournit en entier le nombre suivant, il lui ajoute 1. Une telle opération peut paraitre triviale et peu intéressante. Cependant, elle est très utilisée et est absolument cruciale pour créer des compteurs, des circuits capables de compter ou décompter, qui auront droit à un chapitre dédié. De plus, au-delà de leur utilisation dans les compteurs, les incrémenteurs étaient très utilisés sur les premiers processeurs 8 bits, comme le Z-80, le 6502, les premiers processeurs x86 comme le 8008, le 8086, le 8085, et bien d'autres. Il existe aussi des ''circuits décrémenteurs'', qui décrémentent un opérande, ainsi que des ''circuits incrémenteur-décrémenteur'', qui peuvent incrémenter ou décrémenter, selon comment on les configure. Je ne vais pas détailler ces circuits plus que ça, car de tels circuits sont assez rares, comparé à un circuit incrémenteur simple. ==Le demi-additionneur== Le circuit incrémenteur effectue l'opération suivante : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 Un incrémenteur basique doit donc faire une addition pour chaque colonne, et précisément une addition de deux bits. Il se trouve que la table d'addition est très simple en binaire. Jugez plutôt : * 0 + 0 = 0, retenue = 0 ; * 0 + 1 = 1, retenue = 0 ; * 1 + 0 = 1, retenue = 0 ; * 1 + 1 = 0, retenue = 1. Un circuit capable d'additionner deux bits est appelé un '''demi-additionneur'''. Il dispose d'une sortie S pour la somme, et C pour la retenue (''carry'' an anglais). Il est très simple à construire avec les techniques vues dans les premiers chapitres. Voici sa table de vérité : {|class="wikitable" |- ! Retenue entrante !! Opérande 1 !! !! Retenue sortante !! Bit de somme |- ||0||0|| ||0||0 |- ||0||1|| ||0||1 |- ||1||0|| ||0||1 |- ||1||1|| ||1||0 |} On voit immédiatement que la colonne des retenues donne une porte ET, alors que celle du bit de somme est calculé par un XOR. {| class="flexible" |[[File:1-bit half-adder.svg|class=transparent|centre|Demi-addtionneur.]] |[[File:Half-adder.svg|centre|class=transparent|Circuit d'un demi-addtionneur.]] |} Il existe beaucoup d'autres implémentations alternatives, qui utilisent moins de portes logiques, calculent la retenue plus rapidement, consomment moins d'énergie, et autres. Et il peu être intéressant d'étudier quelques alternatives, surtout qu'elles serviront plus bas, quand on étudiera le circuit incrémenteur du 8085. Une source d'économie est liée à la porte XOR. Une porte XOR est une porte logique assez complexe, qui utilise beaucoup de transistors. En pratique, elle est composée en combinant plusieurs portes logiques ET/OU/NOR/NAND ensemble. Et il se trouve qu'il y a des redondances entre celles-ci et les portes utilisées pour calculer la retenue. Par exemple, rappelons qu'une porte XOR peut être construite avec une porte ET et deux portes NOR, comme illustré ci-dessous. Et il se trouve que la porte ET interne calcule la retenue sortante. En supprimant cette redondance, on économise quelques portes logiques. De plus, on se retrouve avec un demi-additionneur qui calcule le bit de somme à partir de la retenue sortante. [[File:Demi-additionneur avec redondances éliminées.png|centre|vignette|upright=2|Demi-additionneur avec redondances éliminées]] Une implémentation alternative, qui n'utilise que des portes NOR, est la suivante : [[File:Demi-additionneur fait avec des portes NOR et NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NOR et NAND.]] Une implémentation alternative utilise des portes NAND. Pour rappel, il est possible de créer une porte XOR avec 4 portes NAND. La première d'entre elle fait un NAND entre les deux bits d'entrée, ce qui fait qu'elle calcule l'inverse de la retenue sortante. Le tout est illustré ci-dessous. En théorie, on devrait utiliser une porte NON pour récupérer la retenue correcte. Mais nous verrons plus bas que ce n'est pas une obligation. Nous verrons plus bas un exemple où c'est l'inverse de la retenue qui est utilisée dans les calculs, pour rendre les calculs plus rapides. [[File:Demi-additionneur fait avec des portes NAND.png|centre|vignette|upright=2|Demi-additionneur fait avec des portes NAND]] ==L'incrémenteur à propagation de retenue== Maintenant que l'on sait comment additionner deux bits, reprenons l'opération d'incrémentation : <math>a_7</math> <math>a_6</math> <math>a_5</math> <math>a_4</math> <math>a_3</math> <math>a_2</math> <math>a_1</math> <math>a_0</math> + 0 0 0 0 0 0 0 1 ------------------------------ Sur la colonne la plus à droite, il doit ajouter un au bit de poids faible. Pour les colonnes suivantes, il faut additionner le bit de l'opérande avec la retenue de la colonne précédente. En clair, on n'additionne que deux bits à chaque colonne : un 1 sur celle tout à droite, la retenue de la colonne précédente pour les autres. Et cela nous donne une idée de comment faire pour créer le circuit incrémenteur. Il suffit d'utiliser un demi-additionneur par colonne, et de les enchainer les uns à la suite des autres. Chaque demi-additionneur additionne le bit de l'opérande avec la retenue fournie par le demi-additionneur précédent. Le seul qui fait exception est celui pour la colonne de poids faible. Pour celui-là, il doit ajouter 1 au bit de poids faible. Le résultat est appelé un '''incrémenteur à propagation de retenue'''. Il est constitué de demi-additionneurs enchaînés les uns à la suite des autres, du bit de poids faible vers le bit de poids fort. [[File:Circuit incrémenteur.png|centre|vignette|upright=3|Circuit incrémenteur.]] Maintenant, regardons le demi-additionneur le plus à droite, celui pour le bit de poids faible. Son entrée de retenue entrante est mise à 1 pour faire l'incrémentation. Quelques incrémenteurs permettent de configurer cette entrée de retenue à 0 ou à 1, ce qui effectue : soit une opération identité (l'opérande est recopié sur la sortie), soit une incrémentation. Un tel circuit est nommé un '''incrémenteur commandable'''. Nous aurons à utiliser une fois ou deux de tels incrémenteurs commandables dans la suite du cours. L'incrémenteur à propagation de retenue est le plus simple et le plus économe en portes logiques. Mais de tels incrémenteurs sont rarement utilisés. À la place, on leur préfère des incrémenteurs plus rapides, mais qui utilisent plus de portes logiques. De tels incrémenteurs accélèrent le calcul des retenues. En effet, la rapidité d'une incrémentation est limitée par la propagation de la retenue : les retenues commencent à être calculées au bit de poids fort et on doit les calculer une par une, jusqu’à atteindre le bit de poids fort. Et cette "propagation des retenues" prend du temps, d'autant plus de temps que l'opérande est longue. Il y a deux optimisations principales, appelées le ''carry skip'' et l'anticipation de retenue, que nous allons décrire ci-dessous. ==Les incrémenteurs ''carry skip''== L'optimisation '''''carry skip''''' effectue l'incrémentation, non pas bit par bit, mais par paquets de deux bits. Le résultat est que l'incrémentation est deux fois plus rapide, ou presque. Le circuit incrémenteur est donc composé en enchainant non pas des demi-additionneurs, mais des '''incrémenteurs 2 bits''' qui incrémentent un opérande de deux bits. [[File:Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits.png|centre|vignette|upright=2.5|Circuit incrémenteur optimisé, faisant l'incrémentation par paquet de deux bits]] Reste à concevoir l'incrémenteur 2 bits. ===Les optimisations au niveau des transistors et l'exemple de l'incrémenteur du 8085 d'Intel=== Une première solution part de deux demi-additionneurs et effectue quelques simplifications au niveau des transistors et des portes logiques. Par exemple, l'Intel 8085 a utilisé un circuit optimisé, fabriqué avec des portes NAND et NOR. La raison est qu'avec les technologies de transistors CMOS actuelles, les portes NAND et NOR utilisent moins de transistors que les portes ET et OU. Et cette possibilité a été utilisée pour effectuer des simplifications assez mineures, mais toujours bonnes à prendre. Mais nous ne pouvons pas en parler en détail ici, car nous n'avons pas encore parlé en détail des transistors. Cependant, un exemple bien précis nous est accesible : celui de l’incrémenteur du processeur 8085 d'Intel. Le processeur 8085 d'Intel est un processeur 8 bits très ancien. Il contenait un incrémenteur 16 bits, qui était utilisé pour calculer des adresses mémoire. Et cet incrémenteur était un incrémenteur à propagation de retenue optimisé. Il utilisait lui aussi des incrémenteurs 2 bits un peu modifiés. L'idée était que les retenues sortant des colonnes paires étaient inversées, les colonnes impaires faisaient les calculs à partir de cette retenue inversée. Les demi-additionneurs des colonnes impaires n'étaient donc pas les mêmes que ceux des colonnes paires. Leurs tables de vérité sont différentes, leurs circuits aussi, et aucun des deux ne ressemble à un demi-additionneur normal. En réalité, ils sont fabriqués à partir des implémentations vues plus haut, qui utilisent uniquement des portes NAND ou uniquement des portes NOR. Pour comprendre l'intérêt de faire ainsi, nous devons préciser une chose importante : avec les technologies CMOS utilisées pour les processeurs depuis les années 70, les portes logiques les plus simples sont les portes NON, NOR et NAND. Les portes ET/OU sont fabriquées en combinant des portes NOR/NAND avec une porte NON, ce qui prend plus de transistors. Un demi-additionneur est donc fabriqué comme illustré ci-dessous, en logique CMOS. Seules les portes pour le calcul de la retenue sont indiquées, la porte XOR pour le bit de somme est fabriquée à partir de plusieurs portes logiques. [[File:Demi-additionneur en CMOS.png|centre|vignette|upright=2|Demi-additionneur en CMOS]] Si on enchaine deux demi-additionneurs, cela donne ceci : [[File:Brique de base de l'incrémenteur du 8085.png|centre|vignette|upright=2|Brique de base de l'incrémenteur du 8085]] La retenue doit donc traverser quatre portes logiques, dont deux portes NON. En inversant la retenue, les portes en jaune dans le schéma précédent se simplifient. Il suffit d'utiliser la loi de de Morgan pour trouver un circuit équivalent aux portes jaunes, qui n'est autre qu'une porte NOR couplée à une porte NON. Un autre moyen d'obtenir le même résultat est de prendre un demi-additionneur fabriqué avec uniquement des portes NOR, et de retirer la porte NON adéquate. Il faut ensuite corriger l'entrée de retenue de la porte XOR, pour qu'elle fasse l'addition avec la retenue correctement. Le résultat est illustré ci-dessous. [[File:Incrémenteur 2 bits de l'incrémenteur du 8085.png|centre|vignette|upright=2|Incrémenteur 2 bits de l'incrémenteur du 8085]] Le circuit utilise le même nombre de portes logiques, il n'économise pas de transistors. Par contre, la retenue n'a plus qu'à traverser deux portes logiques, au lieu de quatre. La propagation de la retenue est donc plus rapide, l'incrémentation est donc plus rapide. ===Les incrémenteurs 2 bits ''carry skip''=== Une solution alternative fabrique des incrémenteurs 2 bits qui calculent séparément les deux bits du résultat et la retenue sortante. La retenue sortante est calculée à partir des bits de l’opérande, sans propager des retenues. Ainsi, la retenue sortante est connue en avance, sans passer par deux demi-additionneurs. Pour créer un tel incrémenteur, le mieux est de partir de sa table de vérité. {|class="wikitable" |- ! Opérande !! Retenue entrante !! !! Retenue sortante !! Résultat |- | 00 || 0 || || 0 || 00 |- | 01 || 0 || || 0 || 01 |- | 10 || 0 || || 0 || 10 |- | 11 || 0 || || 0 || 11 |- | colspan="5" | |- | 00 || 1 || || 0 || 01 |- | 01 || 1 || || 0 || 10 |- | 10 || 1 || || 0 || 11 |- | 11 || 1 || || 1 || 00 |} Elle nous dit que la retenue sortante ne vaut 1 que dans un seul cas : les deux bits d'opérande valent 1, la retenue entrante vaut 1. Elle se calcule alors avec une porte ET à trois entrées. Pour les deux bits du résultat, les équations logiques ne donnent pas un résultat satisfaisant. La solution la plus simple est d'utiliser deux demi-additionneurs et de retirer les portes logiques superflues. Le résultat est alors un '''incrémenteur 2 bits ''carry skip''''', où la retenue sortante est calculée séparément du reste. [[File:Incrémenteur carry skip 2 bits.png|centre|vignette|upright=2.5|Incrémenteur ''carry skip'' 2 bits]] ==Les incrémenteurs à anticipation de retenue== L''''anticipation de retenue''' calcule la retenue d'une colonne sans attendre les retenues des colonnes précédentes. Dans le cas idéal, toutes les retenues sont calculées en parallèle, en même temps, et sont ensuite envoyées aux demi-additionneurs. Il s'agit d'une optimisation qui est utilisée pour l'incrémentation, l'addition et d'autres opérations similaires. Pour l'incrémentation, déterminer la retenue ne demande pas de calculs complexes, contrairement à l'addition. [[File:Incrémenteur à anticipation de retenues, 8 bits.png|centre|vignette|upright=2.5|Incrémenteur à anticipation de retenues, 8 bits.]] Pour le comprendre, on peut regarder comment la retenue sortant d'un demi-additionneur est formée. Elle est calculée en faisant un ET logique entre la retenue entrante et le bit d'opérande. Une retenue est donc un ET logique entre toutes les retenues précédentes. Un incrémenteur à anticipation de retenue utilise donc une porte ET à plusieurs entrées pour calculer une retenue. [[File:Anticipation de retenue pour un bit du résultat, incrémenteur.png|centre|vignette|upright=2.5|Anticipation de retenue pour un bit du résultat, incrémenteur]] En théorie, on peut utiliser une porte ET à plusieurs entrées pour chaque bit de l'opérande. Cependant, cela entrainera un cout en transistors très important. Pour éviter de gaspiller trop de portes logiques, une solution est de mélanger anticipation de retenues et propagation de retenue. Par exemple, pour un incrémenteur 32 bits, on peut découper l'opérande en 4 octets : on anticipe les retenues pour chaque octet, mais l'incrémentation de chaque octet se fait avec propagation de retenue et/ou ''carry skip''. [[File:Incrémenteur à anticipation de retenues.png|centre|vignette|upright=3|Incrémenteur hybride utilisant partiellement l'anticipation de retenues.]] Quelques processeurs utilisaient l'anticipation de retenues. Par exemple, le processeur Z-80 de Zilog utilisait un incrémenteur pour des nombres de 16 bits, ce qui demandait des performances assez élevées. Et cet incrémenteur utilisait à la fois anticipation de retenues et ''carry skip''. Il était découpé en quatre blocs avant anticipation de retenues entre eux : un bloc regroupant les 7 bits de poids faible, suivi par un bloc de 5 bits, lui-même suivi par un bloc de 3 bits, terminé par un dernier bit isolé. A l'intérieur de ces blocs, les bits sont regroupés en paires utilisant le ''carry skip''. Pour ceux qui veulent en savoir plus sur cet incrémenteur, voici un lien sur le sujet : * [https://www.righto.com/2013/11/the-z-80s-16-bit-incrementdecrement.html The Z-80's 16-bit increment/decrement circuit reverse engineered]. <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les circuits de sélection | prevText=Les circuits de sélection | next=Les bascules : des mémoires de 1 bit | nextText=Les bascules : des mémoires de 1 bit }} </noinclude> n2x0pjgvh2u3ljzm05wgv8izk286m5o Dictionnaire de philosophie/Timothy Williamson 0 83962 768469 768379 2026-06-24T04:27:31Z PandaMystique 119061 768469 wikitext text/x-wiki {{DicoPhilo|Timothy Williamson|lecture=oui}} [[Fichier:Professor Timothy Williamson (cropped).JPG|vignette|upright=1.1|Timothy Williamson.]] Philosophe britannique né à Uppsala, en Suède, en 1955, Timothy Williamson compte parmi les figures les plus influentes de la philosophie analytique contemporaine. Titulaire de la chaire Wykeham de logique à l'université d'Oxford de 2000 à 2023, il a exercé une influence majeure sur plusieurs domaines que l'on tenait pour bien distincts : la théorie du vague, l'[[Dictionnaire de philosophie/Épistémologie|épistémologie]], la [[Dictionnaire de philosophie/Métaphysique|métaphysique]] de la modalité et la réflexion sur la méthode même de la philosophie. Une thèse le rendit d'abord célèbre, et elle prend la forme d'un paradoxe assumé. Nos mots vagues, comme « chauve » ou « tas », ont une extension déterminée : il existe, pour chacun, une frontière qui sépare les cas où le mot s'applique des cas où il ne s'applique pas. Simplement, dans les cas limites, nous sommes hors d'état de savoir où passe cette frontière. Le vague n'est donc pas, pour Williamson, une indétermination des choses ; c'est une certaine forme de notre ignorance<ref>Sur l'épistémicisme comme théorie de ce en quoi le vague consiste, et non comme négation du vague, voir ''Vagueness'', Londres, Routledge, 1994, chap. 7-8, et la préface.</ref>. De cette idée première, qui réhabilite la logique classique là où plusieurs approches concurrentes proposaient de la réviser, procède une œuvre d'une rare unité. On y retrouve partout la même conviction : il existe un monde indépendant de nous, la [[Dictionnaire de philosophie/Connaissance|connaissance]] en est la pierre angulaire, et la philosophie ne diffère pas en nature des autres formes d'enquête. == Repères biographiques == [[Fichier:New College, Oxford 2011 04.jpg|vignette|New College (Oxford), dont Williamson est fellow depuis 2000.]] Williamson naît à Uppsala de parents britanniques. Sa formation se fait tout entière à Oxford, au collège de Balliol, où il étudie d'abord les mathématiques et la philosophie, puis prépare un doctorat de philosophie qu'il soutient au tout début des années 1980, sous une direction qui passa successivement de David Bostock à Bill Newton-Smith, puis à Michael Dummett. Cette double éducation laisse une marque durable. Le goût de la précision formelle, l'aisance dans la logique modale quantifiée, le refus de toute approximation dans la conduite d'un argument tiennent sans doute à cette formation initiale. Ses premiers postes le mènent hors d'Oxford. Il enseigne au Trinity College de Dublin, de 1980 à 1988, avant de revenir comme fellow et tuteur à University College, à Oxford. En 1995, l'université d'Édimbourg lui confie la chaire de logique et de métaphysique, qu'il occupe cinq ans. L'année 2000 marque sa consécration institutionnelle : il est élu à la chaire Wykeham de logique d'Oxford, une chaire que Dummett avait occupée de 1979 à 1992, et dont il devient ainsi l'un des successeurs<ref>Dummett occupa la chaire Wykeham de logique de 1979 à 1992 ; Williamson y fut élu en 2000 et l'occupa jusqu'en 2023. Williamson ne succéda donc pas immédiatement à Dummett.</ref>. Fellow de New College, il y demeure jusqu'en 2023, date à laquelle il prend le titre de professeur émérite tout en continuant d'y enseigner et d'y diriger des recherches. À cette base oxonienne s'ajoutent, au fil des ans, de nombreux postes de visite, parmi lesquels une charge régulière de professeur invité à Yale, où il se rend quelques semaines chaque année, et une affiliation à l'université de la Suisse italienne. Membre de la British Academy et de la Royal Society of Edinburgh, ancien président de l'Aristotelian Society et de la Mind Association, il a formé ou codirigé un grand nombre de doctorants, dont plusieurs occupent aujourd'hui des positions de premier plan. Il écrit aussi pour un public plus large, dans le Times Literary Supplement comme dans la rubrique de philosophie du New York Times, signe d'une volonté constante de faire descendre les questions abstraites dans la conversation commune. [[Fichier:Michael Dummett September 2004.jpg|vignette|Michael Dummett, qui dirigea en partie sa thèse et le précéda à la chaire Wykeham.]] Son parcours épouse, à sa manière, l'histoire de la philosophie analytique des cinquante dernières années. Formé dans le sillage de Dummett et du tournant linguistique, cette idée selon laquelle les problèmes philosophiques seraient au fond des problèmes sur le langage, Williamson s'en est progressivement détaché pour reconstruire une métaphysique et une épistémologie pleinement réalistes. Il représente ainsi le moment où la discipline, après avoir longtemps suspecté ses propres ambitions spéculatives, ose de nouveau parler du monde et non plus seulement de nos façons d'en parler. == Un tempérament et deux convictions == Avant d'entrer dans le détail des thèses, arrêtons-nous sur l'esprit qui les anime : c'est lui qui donne à l'œuvre sa cohérence. Williamson pratique la philosophie en homme convaincu que les désaccords se tranchent. Là où une tradition héritée du second Wittgenstein voyait dans la philosophie une thérapie, un travail patient pour nous délivrer de fausses questions, il tient les questions philosophiques pour de vraies questions, pourvues de réponses vraies ou fausses, dont on s'approche par le travail de l'argument. Le titre à demi provocateur de son dialogue de 2015, ''Tetralogue: I'm Right, You're Wrong'', dit assez cette humeur : on peut respecter son interlocuteur sans cesser de penser qu'il se trompe. Deux idées reviennent d'un livre à l'autre, qu'il vaut mieux nommer dès l'abord. La première est une découverte faite très tôt et sans cesse reprise : celle de la structure de la connaissance inexacte. Nos capacités de discrimination sont grossières ; entre deux situations imperceptiblement différentes, nous ne saurions dire laquelle nous place du bon côté d'une frontière. De ce fait élémentaire, Williamson tire un principe qu'il nomme en anglais ''margin for error'', la marge d'erreur : pour qu'une observation nous donne un savoir, il y faut une marge de sécurité, faute de quoi nous aurions tout aussi bien pu nous tromper. Ce principe, né de l'étude des relations d'indiscernabilité dans son premier livre, irrigue ensuite sa théorie du vague, puis sa théorie de la connaissance. La seconde est une conviction de méthode : la philosophie n'occupe aucune position d'exception parmi les savoirs, elle ne possède ni faculté propre ni méthode purement [[Dictionnaire de philosophie/A priori|a priori]], elle progresse, comme les sciences, par inférence vers la meilleure explication. Présente dès ''The Philosophy of Philosophy'', en 2007, cette thèse se déploie jusqu'à ses essais d'éthique de 2025, étendue à des territoires toujours nouveaux ; c'est elle que recouvrira, de façon de plus en plus assumée, le mot d'anti-exceptionnalisme. L'une et l'autre reposent sur une conviction plus profonde : le réalisme. Il y a une manière dont les choses sont, indépendamment de ce que nous en savons. La bivalence, cette thèse sémantique selon laquelle toute proposition est vraie ou fausse, et la logique classique qui gouverne les inférences valides restent, à ses yeux, les meilleurs instruments pour traiter nos énoncés sur le monde. Non qu'elles le décriraient à la façon d'une théorie physique : elles s'imposent parce qu'elles figurent dans la meilleure théorie d'ensemble de l'inférence et de la signification. Et notre ignorance, si vaste soit-elle, ne doit jamais être confondue avec une indétermination des choses elles-mêmes. Cette distinction, banale en apparence, suffit à départager Williamson de la plupart de ses adversaires. == Les premiers travaux : identité, indiscernabilité, critères == [[Fichier:Young frege.jpg|vignette|Gottlob Frege, dont le critère d'identité des directions sert de point de départ aux premiers travaux de Williamson.]] On présente parfois l'œuvre comme si elle commençait avec le paradoxe du tas. Ce serait oublier les premiers travaux, où se forge pourtant l'outil dont toute la suite tirera parti. Dès 1986, dans un article au titre austère, « Criteria of Identity and the Axiom of Choice », puis plus amplement dans son premier livre, ''Identity and Discrimination'', paru en 1990, Williamson reprend une question que les philosophes posent depuis Frege : qu'est-ce qu'un critère d'identité<ref>« Criteria of Identity and the Axiom of Choice », ''The Journal of Philosophy'', vol. 83, n° 7, 1986, p. 380-394 ; ''Identity and Discrimination'', Oxford, Basil Blackwell, 1990. L'analyse établit que, lorsque la relation de base est réflexive, symétrique mais non transitive, aucune relation n'obéit à la contrainte « forte » d'un critère d'identité, et que plusieurs y obéissent au sens « faible », l'existence d'un tel critère étant équivalente à l'axiome du choix.</ref> ? Frege en avait donné l'exemple canonique. Pour penser la direction d'une droite, disait-il, il faut d'abord savoir ce que c'est, pour deux droites, que d'être parallèles : la direction de la droite ''a'' est identique à la direction de la droite ''b'' si et seulement si ''a'' et ''b'' sont parallèles. Un critère d'identité, c'est cela : une relation entre des objets de départ, ici les droites, qui fixe l'identité d'objets dérivés, ici les directions. Et pour faire ce travail, la relation doit posséder une forme bien précise, celle des relations d'équivalence : réflexive, symétrique et transitive, à l'image de l'identité elle-même. Or Williamson met le doigt sur un cas où le candidat le plus naturel échoue à remplir cette condition. Cherchons un critère d'identité pour la couleur perçue. La relation qui s'impose est l'indiscernabilité : deux échantillons ont la même couleur perçue lorsque l'œil ne parvient pas à les distinguer. Mais cette relation a un défaut qui la disqualifie : elle n'est pas transitive. Un premier échantillon peut être indiscernable d'un deuxième, le deuxième d'un troisième, et le premier se distinguer pourtant nettement du troisième ; de minuscules écarts, insensibles un à un, finissent par s'additionner. L'indiscernabilité ne peut donc pas tenir lieu de critère d'identité, puisqu'un critère doit être transitif et qu'elle ne l'est pas. La suite de l'analyse est d'une grande technicité, et c'est là qu'intervient l'axiome du choix, ce principe de la théorie des ensembles qui autorise à prélever un élément dans chacun des membres d'une collection, fût-elle infinie. Williamson démontre un résultat en deux volets. Là où la relation de départ n'est pas transitive, aucune relation ne peut servir de critère d'identité au sens fort ; et si l'on se contente d'un critère au sens faible, l'axiome du choix garantit qu'il en existe, mais plusieurs à la fois, sans qu'aucun ait un meilleur titre que les autres à passer pour le bon. Mieux, l'hypothèse même qu'un tel critère existe toujours s'avère équivalente à l'axiome du choix. La conséquence inquiète notre confiance ordinaire dans l'identité : partout où la transitivité de l'indiscernabilité se brise, nos jugements d'identité perçue perdent toute valeur de vérité déterminée, et le concept lui-même menace de n'être pas bien défini. Williamson illustre la même structure par l'identité personnelle, par ces cas de fission où une personne se scinderait en deux continuateurs : auquel des deux faut-il l'identifier ? Aucune réponse ne s'impose, et le choix paraît arbitraire. Ce premier livre n'est pas un exercice isolé de logique. Il contient en germe presque tout ce qui suivra. L'idée que des différences imperceptibles s'accumulent jusqu'à devenir perceptibles, que nos capacités de discrimination sont par nature grossières, qu'il faut une certaine marge entre deux situations pour pouvoir les départager en connaissance de cause : voilà déjà le principe de marge d'erreur. Il reparaîtra au cœur de la théorie du vague, puis de la théorie de la connaissance. La structure découverte à propos des couleurs, transposée aux significations, puis aux états de connaissance, deviendra la matrice de toute l'œuvre<ref>Le lien entre l'indiscernabilité non transitive et le principe de marge d'erreur est noué dans ''Identity and Discrimination'', 1990, puis formalisé dans « Inexact Knowledge », ''Mind'', vol. 101, 1992, et dans ''Vagueness'', 1994, chap. 8 (p. 229 et suiv.). La marge d'erreur y est posée comme condition de fiabilité : une croyance ne vaut comme connaissance que si la proposition reste vraie dans tous les cas suffisamment semblables.</ref>. == Le vague et l'ignorance == [[Fichier:Color gradient illustrating a sorites paradox.png|vignette|Un dégradé continu : à partir de quelle nuance le rouge cesse-t-il d'être rouge ? L'absence de frontière visible est au cœur du sorite.]] Sa notoriété philosophique commence surtout avec un casse-tête vénérable, le sorite, du grec ''sôros'', le tas. Un seul grain de blé ne fait pas un tas ; ajouter un grain à ce qui n'est pas un tas ne saurait le transformer en tas ; donc, de proche en proche, dix mille grains ne font toujours pas un tas. La conclusion est manifestement absurde, et pourtant chacune des prémisses paraît irréprochable. Le paradoxe vaut pour tous les prédicats vagues de notre langue : « chauve », « grand », « mince », « rouge ». Combien de cheveux faut-il perdre pour devenir chauve ? À quel instant précis l'enfant que nous fûmes a-t-il cessé d'être un enfant ? Ces questions semblent n'admettre aucune réponse, et c'est cette absence apparente de frontière nette qui paraît constituer le vague lui-même. Le premier tiers de ''Vagueness'' est d'ailleurs une histoire, conduite avec une érudition que l'on n'attend pas toujours d'un logicien<ref>''Vagueness'', chap. 1, pour l'histoire du paradoxe, de Chrysippe à Frege et Russell.</ref>. Williamson y exhume la longue carrière du paradoxe, depuis les Mégariques qui l'inventèrent jusqu'aux logiciens modernes qui le redécouvrirent. Il s'attarde sur la réponse de Chrysippe le stoïcien, qui se taisait avant la question embarrassante, comme un cocher retient ses chevaux au bord du précipice, et il note que les stoïciens, loin de nier l'existence d'une coupure nette, l'acceptaient au contraire de bon cœur. Il rappelle que Leibniz, répondant à Locke, discutait déjà du Tas et du Chauve, que Hegel se servait du sorite pour illustrer le passage du quantitatif au qualitatif, l'eau qui se change soudain en vapeur ou en glace. Avec Frege et Russell, le vague redevient une menace pour la logique : Frege le bannissait comme un défaut du langage ordinaire, Russell le rattachait à la non-transitivité de l'indiscernabilité et au seuil de la discrimination. En reconstruisant cette tradition, Williamson ne fait pas seulement œuvre d'historien : il montre que sa propre solution, l'idée d'une frontière nette mais cachée, a des ancêtres, et qu'elle est moins extravagante qu'elle n'en a l'air. Trois grandes stratégies se partageaient le terrain lorsque Williamson publie ''Vagueness'', en 1994. La première, issue des logiques à valeurs multiples, propose de remplacer le couple vrai-faux par un continuum de degrés de vérité : « Il est chauve » serait vrai à 0,6, ni tout à fait vrai ni tout à fait faux. La deuxième, la méthode des survaluations, conserve le vrai et le faux mais admet que certaines propositions n'ont aucune valeur de vérité dans les cas limites ; une phrase ne devient vraie que si elle l'est sous toutes les façons admissibles de rendre le terme précis. La troisième, le nihilisme, conclut du paradoxe que les prédicats vagues sont tout simplement incohérents, qu'il n'y a ni tas ni chauves. Williamson examine ces trois voies avec une patience d'horloger, et les écarte l'une après l'autre, parce que toutes paient leur solution d'un sacrifice : elles renoncent à la logique classique, ou à la bivalence, ou aux choses mêmes. La thèse qu'il leur substitue déconcerte au premier abord, et il ne s'en cache pas. Sa préface s'ouvre sur un aveu : ce livre, écrit-il, est né de ses tentatives pour réfuter sa propre thèse principale, à savoir que le vague consiste dans notre ignorance des frontières nettes de nos concepts, et qu'il n'exige donc aucune révision de la logique standard<ref>La préface de ''Vagueness'' présente le livre comme né de tentatives pour réfuter la thèse épistémique : le vague consiste dans notre ignorance des frontières nettes de nos concepts.</ref>. L'idée est la suivante. Il existe bel et bien un nombre de cheveux à partir duquel on est chauve : un homme avec ce nombre de cheveux est chauve, un homme avec un cheveu de plus ne l'est pas. La coupure existe, mais nous ne pouvons savoir où elle passe. Le vague n'est pas une propriété du monde, une indétermination des faits ; c'est une variété particulière de notre ignorance. Cette position, que l'on nomme aujourd'hui épistémicisme, permet de tout conserver : la bivalence, le tiers exclu, la logique classique dans son intégrité. Le sorite est alors résolu : sa prémisse inductive, l'idée qu'un grain de plus ne fait jamais la différence, est tout bonnement fausse, car il existe bel et bien un grain qui la fait, même si nous ignorons lequel. Williamson ne nie pourtant pas que nos mots soient vagues : c'est même cette vagueur qu'il entreprend d'expliquer, et son originalité tient à ce qu'il en propose une théorie, qui l'identifie à une ignorance plutôt qu'à un flou des choses. Reste alors l'objection qui vient aussitôt à l'esprit, et qui faisait jusque-là figure de réfutation : si ces frontières existaient, nous devrions pouvoir les trouver ; or nous ne le pouvons pas ; donc elles n'existent pas. Tout l'effort du livre consiste à désamorcer ce raisonnement en expliquant pourquoi, si elles existaient, elles nous demeureraient par principe inaccessibles. L'explication mobilise deux ressorts. Le premier est la manière dont le sens d'un mot dépend de l'usage que nous en faisons collectivement. La signification de « mince » est fixée par l'immense réseau de nos dispositions à l'employer ou à le refuser ; or aucun de nous ne peut surveiller ce réseau dans tous ses détails, ni rendre l'usage qu'il fait du mot à un instant donné parfaitement sensible à l'ensemble dont il dépend. Le second ressort est la marge d'erreur. Williamson le montre par un exemple où il se prend lui-même pour cobaye. La phrase « TW est mince » est peut-être vraie, mais elle aurait très facilement pu être fausse, sans que ses mensurations changent d'un pouce, pour peu que l'usage du mot « mince » eût été tant soit peu différent, ce qui était parfaitement possible. Et celui qui prononce assertivement cette phrase aurait tout aussi facilement pu la prononcer à faux, car sa décision de l'énoncer n'était pas sensible à tous les menus déplacements d'usage qui l'auraient rendue fausse. Une croyance ne vaut comme connaissance que si elle n'aurait pas pu se tromper aussi aisément. Près de la frontière, cette condition n'est jamais remplie, et notre ignorance n'y est donc pas accidentelle, mais structurelle. On reconnaît ici, transposé des couleurs aux significations, le mécanisme étudié dans ''Identity and Discrimination''. Un mot vague est entouré d'autres significations possibles, infinitésimalement proches, que ceux qui les manieraient ne sauraient distinguer de la sienne ; et c'est cette indiscernabilité des sens voisins qui nous voile la frontière. La théorie du vague rejoint enfin l'épistémologie par un autre biais, celui du principe que les logiciens écrivent KK : si l'on sait quelque chose, sait-on que l'on le sait ? Williamson répond non. Reprenons l'exemple de l'arbre devant lequel il passe presque chaque jour depuis des années, sans jamais le mesurer. Sa connaissance de la hauteur de cet arbre est inexacte : sa vue, sa mémoire, son sens des proportions sont imparfaits. On peut construire un modèle où la relation entre situations compatibles avec ce que l'on sait n'est pas transitive, exactement comme l'indiscernabilité des hauteurs ; et le principe KK s'y effondre : on peut savoir sans pour autant savoir que l'on sait. Le sorite ne menace donc pas le prédicat « tas » ; il menacerait, tout au plus, le prédicat « tas connu », et seulement si l'on acceptait KK. Sans ce principe, une itération de savoir se perd à chaque pas, et le paradoxe s'épuise avant d'atteindre sa conclusion fausse<ref>« Inexact Knowledge », ''Mind'', 1992, p. 237-238, et ''Vagueness'', 1994, chap. 8 : le diagnostic du sorite pour la connaissance procède en niant le principe KK, lui-même conséquence du principe de marge d'erreur. L'analyse est reprise dans ''Knowledge and Its Limits'', 2000, chap. 4-5.</ref>. == La connaissance d'abord == Pendant un demi-siècle, l'épistémologie de langue anglaise a tourné autour d'un projet : analyser la connaissance, c'est-à-dire la décomposer en éléments plus simples. La formule héritée de Platon en donnait la première version : connaître, ce serait croire quelque chose de vrai et de justifié. En 1963, un article de trois pages d'Edmund Gettier ruina cette définition par deux contre-exemples, et ouvrit une longue chasse à la condition manquante qui réparerait la formule<ref>Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, 1963, p. 121-123.</ref>. Toutes les tentatives échouèrent, chacune appelant un nouveau contre-exemple. Williamson propose alors de renverser l'ordre des priorités : et si la connaissance ne se laissait pas analyser, parce qu'elle était première ? Il s'agit d'un renversement plutôt que d'une abolition : Williamson ne prétend pas clore une fois pour toutes le projet d'analyse de la connaissance, mais il en inverse la direction et propose d'en faire l'économie. Au lieu de tenir la connaissance pour un composé de croyance, de vérité et d'on ne sait quel ingrédient supplémentaire, il en fait le point de départ, le concept à l'aide duquel on éclaire les autres. ''Knowledge and Its Limits'', paru en 2000, porte ce programme : la connaissance d'abord, ''knowledge first''. La connaissance y est présentée comme un état mental à part entière, et même comme l'état mental factif le plus général, celui qui chapeaute toute la famille des attitudes qui ne peuvent porter que sur du vrai<ref>''Knowledge and Its Limits'', Oxford, Oxford University Press, 2000, chap. 1 : la connaissance est un état mental factif, et le plus général d'entre eux, en ce sens que tout état factif implique la connaissance de son contenu.</ref>. Voir que la porte est ouverte, se souvenir qu'on l'a fermée, s'apercevoir qu'il pleut : autant d'états qui enveloppent la vérité de leur contenu, et qui sont, chacun, une manière de savoir. On ne définit pas la connaissance ; on la situe, au sommet de cette famille. Si Williamson tient tant à cette indécomposabilité, qu'il nomme la primalité, c'est que la connaissance explique ce que la simple croyance n'explique pas. Il en donne un exemple resté célèbre, celui du cambrioleur. Un voleur qui sait qu'un diamant se trouve dans la maison la fouillera toute la nuit, sans se décourager ; celui qui le croit seulement, même avec raison et de bon droit, risque d'abandonner plus tôt, parce que sa relation au fait est plus fragile. La connaissance, attache plus solide au monde, soutient l'action avec une constance que la croyance n'a pas. Or si l'on décompose le savoir en un noyau interne, la croyance, et un supplément externe, la vérité plus quelque garantie, on perd cette unité explicative : l'explication renvoie à la connaissance prise en bloc, non à une conjonction de deux facteurs indépendants. À cet état premier, Williamson refuse une propriété que la tradition lui prêtait volontiers : la transparence, ou comme il dit la luminosité. Une condition est lumineuse si, dès qu'elle est remplie, on est en position de savoir qu'elle l'est. On a longtemps cru que nos propres états d'esprit étaient ainsi faits, qu'il suffisait d'éprouver une douleur ou de sentir le froid pour savoir qu'on les éprouve. Williamson construit contre cette idée un argument serré, fondé une fois encore sur la marge d'erreur<ref>''Knowledge and Its Limits'', chap. 4 et 5, pour l'argument contre la luminosité et la notion de sécurité (''safety'').</ref>. La conséquence est une réfutation du principe KK déjà rencontré à propos du vague : on peut savoir sans savoir que l'on sait, parce que la connaissance exige une marge de sécurité, la sécurité que l'on n'aurait pas pu aisément se tromper. Cette notion de sécurité fournit d'ailleurs la caractérisation positive du savoir que Williamson est prêt à concéder, non comme une analyse, mais comme une vérité éclairante : si l'on sait, on n'aurait pas pu facilement avoir tort dans un cas semblable. Une croyance est sûre lorsque, dans tous les cas suffisamment proches où on la formerait sur une base semblable, elle serait vraie. La sécurité n'est pas une condition interne ; elle dépend de la configuration du monde autour de nous. C'est dire combien l'épistémologie de Williamson tourne le dos à l'internalisme, à l'idée que tout ce qui compte pour la justification serait accessible par simple réflexion. La connaissance habite le monde, non l'intériorité d'un sujet replié sur ses états. De ce primat de la connaissance, Williamson tire une dernière conséquence, qui a fait couler beaucoup d'encre : notre évidence se réduit à ce que nous savons<ref>''Knowledge and Its Limits'', chap. 9 : l'évidence est la connaissance (''E = K'').</ref>. ''E = K'', écrit-il, l'évidence est la connaissance. Ce dont nous disposons pour étayer nos croyances, ce sur quoi nous raisonnons, n'est ni un donné sensoriel ni un ensemble d'impressions privées, mais l'ensemble des propositions que nous connaissons. Le foyer cognitif cartésien, ce lieu intérieur où l'esprit serait chez lui et ne pourrait se tromper, est un mythe : il n'y a pas de retraite à l'abri du monde. Cette thèse demeure l'une des plus débattues de l'épistémologie récente, et l'article ne lui rendrait pas justice en la présentant comme un acquis. Les internalistes lui reprochent de congédier trop vite l'idée d'une justification accessible de l'intérieur ; les partisans d'une théorie de la justification refusent de renoncer au projet d'analyse ; d'autres contestent que l'on puisse traiter la connaissance comme un état mental factif primitif. Ernest Sosa, par exemple, a objecté que « croire sûrement » serait un état factif plus général que la connaissance, ce qui ruinerait la caractérisation ; Williamson a répliqué que « croire sûrement » n'est pas sémantiquement insécable, et ne saurait donc compter parmi les états factifs primitifs. Le débat n'est pas clos ; il a seulement changé de terrain, ce qui est peut-être la meilleure mesure de l'influence du livre. == La modalité : du possible imaginé au possible réel == La modalité, ce domaine du nécessaire et du possible, occupe Williamson sous deux aspects qu'il importe de ne pas confondre : comment connaissons-nous ce qui aurait pu être, et qu'est-ce, au juste, qui aurait pu être ? La première question est épistémologique, la seconde métaphysique, et il leur a donné des réponses également originales. Sur la connaissance du possible, la conception reçue voulait que nous disposions d'une faculté propre, la conception ou ''conceivability'', qui ferait office de fenêtre sur le possible : ce que je puis concevoir sans contradiction serait possible, ce que je ne puis concevoir serait impossible. Williamson récuse cette image d'une faculté spéciale. Notre savoir des possibilités, soutient-il dans ''The Philosophy of Philosophy'', fait appel à la même aptitude tout ordinaire qui nous sert à évaluer des conditionnels contrefactuels, ces énoncés en « si... alors il en serait allé ainsi » que nous manions à longueur de journée<ref>''The Philosophy of Philosophy'', Oxford, Blackwell, 2007, chap. 5 : la connaissance modale fait appel à la même capacité cognitive que l'évaluation des conditionnels contrefactuels, sans qu'il faille postuler une faculté supplémentaire.</ref>. Pour décider si quelque chose aurait pu se produire, nous développons l'hypothèse et regardons si une contradiction en surgit, exactement comme lorsque nous nous demandons ce qui serait arrivé si nous avions pris l'autre chemin. Or cette aptitude n'a rien d'a priori au sens traditionnel : elle puise abondamment dans notre connaissance du monde, elle est faillible, elle n'est pas transparente. On ne lit pas le possible dans le ciel des idées ; on l'établit, avec les moyens du bord, à partir de ce que l'on sait déjà. Du même coup, les démarches qui prétendent s'appuyer sur un a priori bien net, comme la sémantique à deux dimensions chère à [[Dictionnaire de philosophie/David Chalmers|David Chalmers]], se trouvent fragilisées dans leurs fondements épistémiques<ref>« Armchair Philosophy, Metaphysical Modality and Counterfactual Thinking », ''Proceedings of the Aristotelian Society'', vol. 105, 2005, p. 1-23, et ''The Philosophy of Philosophy'', 2007, chap. 5. La concevabilité y est tenue pour un test peu fiable du possible tant qu'on ne la définit pas par la possibilité même ; l'aptitude réellement à l'œuvre est celle, ordinaire, qui sert à évaluer les conditionnels contrefactuels, de sorte qu'aucune faculté spéciale n'a besoin d'être postulée.</ref>. Reste la seconde question, proprement métaphysique : qu'est-ce qui aurait pu être ? Ici Williamson défend, dans ''Modal Logic as Metaphysics'' (2013), une thèse qu'il nomme le nécessitisme, et qui heurte de front le sens commun. On peut l'énoncer en une formule : nécessairement, tout est nécessairement quelque chose<ref>''Modal Logic as Metaphysics'', Oxford, Oxford University Press, 2013, chap. 1 ; et « Necessitism, Contingentism, and Plural Quantification », ''Mind'', vol. 119, n° 475, 2010, p. 657-748, qui formule la thèse (NNE : nécessairement, tout est nécessairement quelque chose) et la distingue du possibilisme comme du meinongianisme. Le terme retenu pour les objets en question est « contingentement non concret » et non « seulement possible ».</ref>. Autrement dit, rien de ce qui est ne pourrait n'avoir absolument rien été ; et rien, non plus, ne pourrait s'ajouter à ce qu'il y a. Le contingentiste, son adversaire, soutient l'inverse : telle table existe, mais aurait pu n'exister pas du tout, et d'autres choses auraient pu exister qui n'existent pas. Une objection se présente aussitôt : si rien ne peut commencer ni cesser d'être quelque chose, que faire de l'enfant que tel couple aurait pu avoir et n'a pas eu, de la table que ce menuisier aurait pu fabriquer et n'a pas fabriquée ? Ce serait pourtant caricaturer la thèse : le nécessitiste ne dit pas qu'il existe, à côté des choses concrètes, une foule de fantômes seulement possibles. Ce que nous sommes tentés d'appeler un « objet seulement possible », par exemple un enfant possible de Wittgenstein, est en réalité un objet contingentement non concret : il est bel et bien quelque chose, il aurait pu être concret, de chair et d'os, mais il se trouve qu'il ne l'est pas. Il n'est pas un néant, ni un possible flottant entre l'être et le non-être ; il est, sur le mode du non-concret. Williamson prend soin de distinguer cette position de deux autres avec lesquelles on la confond aisément : elle n'est pas le meinongianisme, qui peuplerait le monde d'objets inexistants ; elle n'est pas davantage le possibilisme classique. Le débat embrouillé entre possibilistes et actualistes se laisse, dit-il, reformuler en un débat plus clair et plus maniable, celui du nécessitisme et du [[Dictionnaire de philosophie/Contingence|contingentisme]], qui se joue sur la validité d'une formule logique précise, la formule de Barcan. Si Williamson soutient une thèse aussi contre-intuitive, ce n'est pas par goût du paradoxe, mais par fidélité à sa méthode. Le nécessitisme, montre-t-il, fournit la logique modale quantifiée la plus simple et la plus puissante : il valide la formule de Barcan et sa réciproque, il autorise une sémantique à domaine constant, il évite une foule de complications. Entre deux théories rivales, on choisit comme le physicien choisit entre deux hypothèses : celle qui rend le plus avec le moins. Que la plus simple heurte nos intuitions n'est pas, en soi, un argument contre elle ; nos intuitions sur ce qui aurait pu exister n'ont pas plus d'autorité, sur ce terrain, que le sens commun n'en avait sur la mécanique céleste. == La méthode : l'anti-exceptionnalisme == Tous ces résultats reposent sur une même conception de ce qu'est philosopher, exposée dans ''The Philosophy of Philosophy'' (2007) puis, sous une forme accessible à tous, dans ''Doing Philosophy'' (2018). La thèse y est déjà nette, même si le mot ne s'imposera vraiment que plus tard : c'est ce qu'il appellera, et de plus en plus explicitement, anti-exceptionnalisme<ref>''The Philosophy of Philosophy'', chap. 1 et 7 ; ''Doing Philosophy'', Oxford, Oxford University Press, 2018. La thèse méthodologique est présente dès 2007 ; le qualificatif « anti-exceptionnaliste » ne devient un mot d'ordre explicite que dans les travaux plus récents, du sous-titre de ''Good as Usual'' (2025) à des essais comme « Moral Anti-Exceptionalism ».</ref>. La philosophie, soutient-il, n'occupe aucune position d'exception parmi les savoirs. Elle ne dispose pas d'une faculté spéciale qui lui ouvrirait un accès direct aux essences ; elle ne procède pas par une méthode purement a priori qui la couperait de l'expérience. Elle est de la même famille que les autres enquêtes, simplement plus abstraite et privée de laboratoire. Le cas le plus discuté est celui des intuitions. On répète volontiers que la philosophie se fonde sur des intuitions, ces jugements spontanés que provoquent en nous les expériences de pensée : le wagon fou que l'on peut dévier sur une autre voie, la chambre chinoise, le village où l'on ne sait plus qui est chauve. Williamson conteste cette description. Ce que nous appelons intuition n'est pas le verdict d'une faculté mystérieuse, ni un donné qu'il faudrait recueillir comme on recueille des réponses à un sondage. C'est un simple jugement, exercé sur un cas hypothétique, et il vaut comme source de connaissance pour autant qu'il est compétent, non parce qu'il serait « intuitif ». La même capacité ordinaire d'évaluer des conditionnels contrefactuels, déjà rencontrée à propos du possible, suffit à en rendre compte : juger ce qui se passerait si telle situation se présentait, voilà ce que nous faisons devant une expérience de pensée, et c'est une chose que nous savons faire. De là une conséquence qui dérange les habitudes : la distinction même de l'a priori et de l'a posteriori, sur laquelle tant de débats se sont bâtis, lui paraît trop grossière pour un travail théorique sérieux. Nos connaissances modales, par exemple, ne sont ni purement indépendantes de l'expérience ni purement tirées d'elle ; l'expérience y joue un rôle qui n'est ni de simple justification ni de simple déclenchement, de sorte que la frontière elle-même s'estompe. Une question philosophique se tranche alors par la même méthode que partout : l'inférence vers la meilleure explication, ce que la tradition nomme l'[[Dictionnaire de philosophie/Abduction|abduction]]. On compare des théories rivales, on pèse leur simplicité, leur puissance, leur accord avec ce que l'on tient par ailleurs pour acquis, et l'on retient la meilleure. Rien, en philosophie, n'est gratuit au point de n'imposer aucune contrainte à la réalité : une thèse a des conséquences, et ses conséquences se paient. C'est cette conception qui commande, chaque fois, les choix de Williamson, du nécessitisme à la défense de la logique classique. La question n'est jamais « qu'est-ce qui est évident ? », mais « quelle théorie d'ensemble fait le mieux le travail ? ». == Le dialogue : ''Tetralogue'' == ''Tetralogue'', paru en 2015, est un dialogue à la manière antique : quatre voyageurs se trouvent réunis dans un train et discutent jusqu'au terminus. Sarah défend la science et la raison ; Bob, qu'un guérisseur a guéri, en est venu à croire à la sorcellerie ; Roxana, logicienne intransigeante, traque la moindre incohérence ; Zac, conciliant et relativiste, voudrait que chacun ait raison à sa façon. De ce quatuor naît une comédie d'idées où s'affrontent les attitudes que nous adoptons spontanément face au désaccord. Le propos du livre est de défendre, sans pédantisme, deux thèses jumelles que Williamson tient pour inséparables : la vérité est objective, et nous sommes faillibles. Contre Zac, il s'agit de montrer que la formule « vrai pour moi » ne veut rien dire de cohérent : si une chose est vraie, elle l'est tout court, et croire le contraire à propos du même monde, c'est se tromper, non détenir une autre vérité. Contre une certaine arrogance scientiste, il s'agit de rappeler que reconnaître la possibilité de son erreur n'oblige nullement à renoncer à juger. Le titre, ''I'm Right, You're Wrong'', condense cette double leçon avec une provocation calculée : dans un désaccord véritable, l'un a raison et l'autre tort, et l'admettre n'est pas un manque de tolérance, c'est la condition d'une conversation sérieuse. On respecte mieux autrui en le tenant pour capable de vérité et d'erreur qu'en le confinant poliment dans sa bulle. Le dialogue, sous ses dehors plaisants, est ainsi une défense du réalisme contre le relativisme, ce même réalisme qui gouverne en sous-main toute l'œuvre. == L'éthique et l'action : ''Good as Usual'' == Le dernier grand chantier de Williamson, rassemblé en 2025 sous le titre ''Good as Usual'', dont le sous-titre annonce des essais anti-exceptionnalistes sur les normes, les valeurs et l'action, étend à la philosophie pratique le programme élaboré ailleurs. La thèse directrice est que le normatif ne forme pas un royaume à part. Le bien, la connaissance morale, les normes de la croyance et de l'action ne sont pas plus exceptionnels que le reste ; ils s'étudient avec les mêmes outils, et la connaissance y joue le même rôle central que dans la vie intellectuelle. Prenons d'abord la connaissance morale. Contre l'argument sceptique qui invoque l'ampleur des désaccords moraux pour conclure à l'absence de savoir éthique, Williamson rappelle que la connaissance n'exige qu'une fiabilité locale. Pourvu que l'on admette qu'il y a des vérités morales, il n'y a, soutient-il, aucun obstacle particulier à les connaître. Que des sociétés divergent sur ce qui est juste ne prouve pas que nul ne sait rien en morale, pas plus que l'existence de désaccords perceptifs ne ruine la perception ; on peut être fiable touchant les actions de son propre milieu sans l'être touchant celles d'un milieu lointain. La capacité de reconnaître le bien et le mal est une capacité de reconnaissance comme une autre, faillible et néanmoins source de savoir. Ensuite, la connaissance d'abord s'applique à l'action, et c'est ici qu'il faut restituer exactement les termes de l'analogie, qu'on déforme facilement. Connaître se tient à croire comme produire intentionnellement un état de choses se tient à le désirer<ref>L'analogie remonte à « Knowing and Asserting », ''The Philosophical Review'', vol. 105, n° 4, 1996, p. 489-523 (notamment p. 521) : connaître se tient à croire comme produire intentionnellement un état de choses se tient à le désirer ; les deux assurent l'accord du contenu et du monde, mais selon des directions d'ajustement opposées. Elle est reprise et développée dans ''Good as Usual'', 2025.</ref>. Si je sais que P, alors P ; de même, si je fais en sorte que P, alors P. Mais il ne suffit pas, pour savoir que P, de le croire alors que P se trouve vrai, car l'accord pourrait n'être qu'accidentel ; il ne suffit pas davantage, pour avoir produit P, de l'avoir désiré alors que P se trouve réalisé. La connaissance est le bon cas d'une direction d'ajustement, celle de l'esprit au monde : la croyance vise à se conformer au monde, et la connaissance est la croyance qui y parvient sans hasard. L'action est le bon cas de la direction inverse, celle du monde à l'esprit : le désir vise à conformer le monde à lui, et l'action est le désir qui y parvient sans hasard. Ce qui sépare connaissance et action n'est donc pas le degré de réussite, c'est le sens de l'ajustement. La connaissance est l'entrée du raisonnement pratique, son point de départ ; l'action en est la sortie réussie. De là une norme symétrique de celle de l'assertion : n'agis que sur ce que tu sais. Quand la délibération fonctionne bien, on n'emploie comme prémisse que ce que l'on connaît ; une prémisse simplement crue, sans être sue, est un grain de sable qui dérègle la machine. Williamson y intègre une thèse qu'il défend de longue date avec Jason Stanley, l'intellectualisme touchant le savoir-faire : savoir faire quelque chose, c'est savoir une vérité, et non posséder une aptitude d'une autre nature ; le savoir-faire peut donc fournir une prémisse au raisonnement pratique précisément parce qu'il est un savoir-que. Le même esprit conduit Williamson à reprendre, du côté de la croyance, sa critique de l'internalisme. Il existe plusieurs normes possibles de la croyance : une norme de vérité, une norme d'évidence, une norme de connaissance. Il plaide pour la dernière, sous une forme fonctionnelle : crois seulement ce que tu sais. Et il fait jouer une dernière fois l'argument contre la luminosité pour récuser l'exigence internaliste selon laquelle les fondements de nos jugements devraient nous être accessibles par simple introspection. Le titre du recueil joue d'ailleurs sur les mots : le bien y est traité « comme d'habitude », c'est-à-dire comme le fonctionnement normal, non défectueux, d'êtres engagés dans le monde. Là encore, le geste de Williamson est de ramener la valeur dans le tissu commun de la connaissance et de l'action, au lieu de la reléguer dans une sphère séparée. == Réception et influence == L'œuvre de Williamson a suscité une littérature critique abondante, signe de son importance. Deux volumes collectifs lui ont été consacrés, l'un sur la connaissance, l'autre sur la modalité, chacun accompagné de ses réponses détaillées aux objections<ref>Patrick Greenough et Duncan Pritchard (dir.), ''Williamson on Knowledge'', 2009 ; Mark McCullagh et Juhani Yli-Vakkuri (dir.), ''Williamson on Modality'', 2017.</ref>. Les fronts de discussion sont nombreux. Les internalistes tiennent qu'il a écarté trop vite l'idée d'une justification accessible de l'intérieur. Les défenseurs de la méthode des survaluations, comme Delia Graff Fara, refusent de payer la bivalence au prix de l'intuition qu'aucune coupure nette ne traverse nos prédicats vagues. Les partisans des logiques non classiques rejettent son plaidoyer pour la logique standard. Certains critiques jugent le nécessitisme, avec ses objets contingentement non concrets, d'un coût métaphysique trop lourd. À chacun Williamson répond avec la même rigueur méthodique, en déplaçant le débat sur le terrain qui est le sien, celui de la comparaison des théories ; et c'est souvent cette manière de répondre, autant que les thèses elles-mêmes, qui a marqué ses lecteurs. Son influence tient aussi à autre chose qu'à ses arguments. Il a contribué à légitimer une certaine façon de faire de la philosophie : technique sans être stérile, ambitieuse sans verser dans la spéculation, attentive à la forme logique des problèmes. Son rayonnement passe enfin par l'enseignement. Il a dirigé un grand nombre de thèses, et plusieurs de ses anciens étudiants comptent aujourd'hui parmi les figures montantes de la discipline. Il s'est aussi adressé au grand public, par ses dialogues, par ses petits livres d'initiation, par ses chroniques de presse, convaincu que la philosophie n'a rien à gagner à se retrancher dans un jargon d'initiés. L'auteur de traités exigeants et le pédagogue ne font chez lui qu'une seule personne, fidèle à l'idée que la difficulté ne doit pas être masquée mais apprivoisée. == Conclusion == Ce qui frappe, au terme de ce parcours, c'est l'unité d'une œuvre que la diversité des sujets pourrait faire croire dispersée. Du vague à la connaissance, de la modalité à la méthode, et jusqu'à l'éthique des derniers travaux, une même sensibilité se reconnaît. Un réalisme constant, d'abord : le réel a ses traits indépendamment de nous, et notre ignorance ne doit jamais être prise pour une indétermination des choses. Un attachement à la logique classique, ensuite, défendu non par dogmatisme mais parce qu'elle figure dans la meilleure théorie globale. La conviction, encore, que la connaissance est la pierre angulaire, le concept premier à partir duquel s'éclairent l'évidence, l'assertion, l'action et la valeur. Et, partout, les deux mêmes orientations : la structure de la connaissance inexacte, avec son principe de marge d'erreur, née de l'indiscernabilité non transitive et reparaissant aussi bien dans la théorie du vague que dans l'argument contre la luminosité ; et l'anti-exceptionnalisme, cette idée que la philosophie ne diffère pas en nature des autres enquêtes et procède comme elles par inférence vers la meilleure explication. Williamson aura beaucoup contribué à une certaine idée de la philosophie analytique : une discipline qui traite ses questions avec autant de sérieux théorique que les sciences, sans pour autant céder à l'obscurité ni au relativisme. On peut discuter chacune de ses thèses, et beaucoup le font ; on peut juger le nécessitisme trop coûteux, l'épistémicisme trop hardi, le primat de la connaissance trop exclusif. Reste, par-delà ces désaccords, une exigence de rigueur et une manière de poser les problèmes dont la philosophie de notre temps porte l'empreinte. == Notes et références == {{références|colonnes=2}} == Bibliographie == === Sources primaires (œuvres de Timothy Williamson) === * « Criteria of Identity and the Axiom of Choice », ''The Journal of Philosophy'', vol. 83, n° 7, 1986, p. 380-394. * ''Identity and Discrimination'', Oxford, Basil Blackwell, 1990 (édition augmentée, Wiley-Blackwell, 2013). * ''Vagueness'', Londres, Routledge, 1994. * « Knowing and Asserting », ''The Philosophical Review'', vol. 105, n° 4, 1996, p. 489-523. * ''Knowledge and Its Limits'', Oxford, Oxford University Press, 2000. * ''The Philosophy of Philosophy'', Oxford, Blackwell, 2007 (2e édition augmentée, Wiley-Blackwell, 2021). * « Necessitism, Contingentism, and Plural Quantification », ''Mind'', vol. 119, n° 475, 2010, p. 657-748. * ''Modal Logic as Metaphysics'', Oxford, Oxford University Press, 2013. * ''Tetralogue: I'm Right, You're Wrong'', Oxford, Oxford University Press, 2015. * ''Doing Philosophy: From Common Curiosity to Logical Reasoning'', Oxford, Oxford University Press, 2018 (réédition en poche sous le titre ''Philosophical Method: A Very Short Introduction'', 2020). * ''Suppose and Tell: The Semantics and Heuristics of Conditionals'', Oxford, Oxford University Press, 2020. * (avec Paul Boghossian) ''Debating the A Priori'', Oxford, Oxford University Press, 2020. * ''Overfitting and Heuristics in Philosophy'', Oxford, Oxford University Press, 2024. * ''Good as Usual: Anti-Exceptionalist Essays on Norms, Values, and Action'', Oxford, Oxford University Press, 2025. === Études critiques consacrées à son œuvre === * Patrick Greenough et Duncan Pritchard (dir.), ''Williamson on Knowledge'', Oxford, Oxford University Press, 2009 (avec les « Replies to Critics » de Williamson). * Mark McCullagh et Juhani Yli-Vakkuri (dir.), ''Williamson on Modality'', Londres, Routledge, 2017. === Autres ouvrages et articles cités === * Gottlob Frege, ''Les Fondements de l'arithmétique'' (1884). * Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, 1963, p. 121-123. * Saul Kripke, ''Naming and Necessity'', Oxford, Blackwell, 1980. * David Chalmers, ''The Conscious Mind: In Search of a Fundamental Theory'', Oxford, Oxford University Press, 1996. * Ernest Sosa, ''Knowing Full Well'', Princeton, Princeton University Press, 2011. === Sources biographiques === Les données biographiques (dates, postes, distinctions) proviennent des sources institutionnelles suivantes : * [https://www.philosophy.ox.ac.uk/people/timothy-williamson Page de Timothy Williamson, Faculty of Philosophy, université d'Oxford] * [https://www.new.ox.ac.uk/timothy-williamson Page de Timothy Williamson, New College, Oxford] * [https://www.thebritishacademy.ac.uk/fellows/timothy-williamson-FBA/ Notice « Professor Timothy Williamson FBA », The British Academy (élu Fellow en 1997)] * [https://www.rse.org.uk/fellow/timothy-williamson/ Notice « Professor Timothy Williamson FRSE », The Royal Society of Edinburgh (élu Fellow en 1997)] * [https://www.philosophy.ox.ac.uk/sitefiles/twcvshortnew-v2.pdf Curriculum vitae officiel (université d'Oxford)] == Voir aussi == * {{Page|Épistémologie}} * {{Page|Connaissance}} * {{Page|Métaphysique}} * {{Page|A priori}} * {{Page|Contingence}} * {{Page|Abduction}} * {{Page|Vérité}} * {{Page|David Chalmers}} == Sur Wikisource == Deux textes classiques évoqués dans cet article sont disponibles en texte intégral sur Wikisource : * [[s:Nouveaux Essais sur l’entendement humain|Leibniz, ''Nouveaux Essais sur l'entendement humain'']], où sont discutés le Tas et le Chauve. * [[s:Essai philosophique concernant l’entendement humain|Locke, ''Essai philosophique concernant l'entendement humain'']], dont Leibniz fait son interlocuteur. {{DEFAULTSORT:Williamson}} [[Catégorie:Dictionnaire de philosophie (livre)]] [[Catégorie:Philosophe]] 0hs7l6esfyy5dshj6kgxc21t6vnogkf 768470 768469 2026-06-24T04:27:44Z PandaMystique 119061 768470 wikitext text/x-wiki {{DicoPhilo|Timothy Williamson|lecture=oui}} [[Fichier:Professor Timothy Williamson (cropped).JPG|vignette|upright=1.1|Timothy Williamson.]] Philosophe britannique né à Uppsala, en Suède, en 1955, Timothy Williamson compte parmi les figures les plus influentes de la philosophie analytique contemporaine. Titulaire de la chaire Wykeham de logique à l'université d'Oxford de 2000 à 2023, il a exercé une influence majeure sur plusieurs domaines que l'on tenait pour bien distincts : la théorie du vague, l'[[Dictionnaire de philosophie/Épistémologie|épistémologie]], la [[Dictionnaire de philosophie/Métaphysique|métaphysique]] de la modalité et la réflexion sur la méthode même de la philosophie. Une thèse le rendit d'abord célèbre, et elle prend la forme d'un paradoxe assumé. Nos mots vagues, comme « chauve » ou « tas », ont une extension déterminée : il existe, pour chacun, une frontière qui sépare les cas où le mot s'applique des cas où il ne s'applique pas. Simplement, dans les cas limites, nous sommes hors d'état de savoir où passe cette frontière. Le vague n'est donc pas, pour Williamson, une indétermination des choses ; c'est une certaine forme de notre ignorance<ref>Sur l'épistémicisme comme théorie de ce en quoi le vague consiste, et non comme négation du vague, voir ''Vagueness'', Londres, Routledge, 1994, chap. 7-8, et la préface.</ref>. De cette idée première, qui réhabilite la logique classique là où plusieurs approches concurrentes proposaient de la réviser, procède une œuvre d'une rare unité. On y retrouve partout la même conviction : il existe un monde indépendant de nous, la [[Dictionnaire de philosophie/Connaissance|connaissance]] en est la pierre angulaire, et la philosophie ne diffère pas en nature des autres formes d'enquête. == Repères biographiques == [[Fichier:New College, Oxford 2011 04.jpg|vignette|New College (Oxford), dont Williamson est fellow depuis 2000.]] Williamson naît à Uppsala de parents britanniques. Sa formation se fait tout entière à Oxford, au collège de Balliol, où il étudie d'abord les mathématiques et la philosophie, puis prépare un doctorat de philosophie qu'il soutient au tout début des années 1980, sous une direction qui passa successivement de David Bostock à Bill Newton-Smith, puis à Michael Dummett. Cette double éducation laisse une marque durable. Le goût de la précision formelle, l'aisance dans la logique modale quantifiée, le refus de toute approximation dans la conduite d'un argument tiennent sans doute à cette formation initiale. Ses premiers postes le mènent hors d'Oxford. Il enseigne au Trinity College de Dublin, de 1980 à 1988, avant de revenir comme fellow et tuteur à University College, à Oxford. En 1995, l'université d'Édimbourg lui confie la chaire de logique et de métaphysique, qu'il occupe cinq ans. L'année 2000 marque sa consécration institutionnelle : il est élu à la chaire Wykeham de logique d'Oxford, une chaire que Dummett avait occupée de 1979 à 1992, et dont il devient ainsi l'un des successeurs<ref>Dummett occupa la chaire Wykeham de logique de 1979 à 1992 ; Williamson y fut élu en 2000 et l'occupa jusqu'en 2023. Williamson ne succéda donc pas immédiatement à Dummett.</ref>. Fellow de New College, il y demeure jusqu'en 2023, date à laquelle il prend le titre de professeur émérite tout en continuant d'y enseigner et d'y diriger des recherches. À cette base oxonienne s'ajoutent, au fil des ans, de nombreux postes de visite, parmi lesquels une charge régulière de professeur invité à Yale, où il se rend quelques semaines chaque année, et une affiliation à l'université de la Suisse italienne. Membre de la British Academy et de la Royal Society of Edinburgh, ancien président de l'Aristotelian Society et de la Mind Association, il a formé ou codirigé un grand nombre de doctorants, dont plusieurs occupent aujourd'hui des positions de premier plan. Il écrit aussi pour un public plus large, dans le Times Literary Supplement comme dans la rubrique de philosophie du New York Times, signe d'une volonté constante de faire descendre les questions abstraites dans la conversation commune. [[Fichier:Michael Dummett September 2004.jpg|vignette|Michael Dummett, qui dirigea en partie sa thèse et le précéda à la chaire Wykeham.]] Son parcours épouse, à sa manière, l'histoire de la philosophie analytique des cinquante dernières années. Formé dans le sillage de Dummett et du tournant linguistique, cette idée selon laquelle les problèmes philosophiques seraient au fond des problèmes sur le langage, Williamson s'en est progressivement détaché pour reconstruire une métaphysique et une épistémologie pleinement réalistes. Il représente ainsi le moment où la discipline, après avoir longtemps suspecté ses propres ambitions spéculatives, ose de nouveau parler du monde et non plus seulement de nos façons d'en parler. == Un tempérament et deux convictions == Avant d'entrer dans le détail des thèses, arrêtons-nous sur l'esprit qui les anime : c'est lui qui donne à l'œuvre sa cohérence. Williamson pratique la philosophie en homme convaincu que les désaccords se tranchent. Là où une tradition héritée du second Wittgenstein voyait dans la philosophie une thérapie, un travail patient pour nous délivrer de fausses questions, il tient les questions philosophiques pour de vraies questions, pourvues de réponses vraies ou fausses, dont on s'approche par le travail de l'argument. Le titre à demi provocateur de son dialogue de 2015, ''Tetralogue: I'm Right, You're Wrong'', dit assez cette humeur : on peut respecter son interlocuteur sans cesser de penser qu'il se trompe. Deux idées reviennent d'un livre à l'autre, qu'il vaut mieux nommer dès l'abord. La première est une découverte faite très tôt et sans cesse reprise : celle de la structure de la connaissance inexacte. Nos capacités de discrimination sont grossières ; entre deux situations imperceptiblement différentes, nous ne saurions dire laquelle nous place du bon côté d'une frontière. De ce fait élémentaire, Williamson tire un principe qu'il nomme en anglais ''margin for error'', la marge d'erreur : pour qu'une observation nous donne un savoir, il y faut une marge de sécurité, faute de quoi nous aurions tout aussi bien pu nous tromper. Ce principe, né de l'étude des relations d'indiscernabilité dans son premier livre, irrigue ensuite sa théorie du vague, puis sa théorie de la connaissance. La seconde est une conviction de méthode : la philosophie n'occupe aucune position d'exception parmi les savoirs, elle ne possède ni faculté propre ni méthode purement [[Dictionnaire de philosophie/A priori|a priori]], elle progresse, comme les sciences, par inférence vers la meilleure explication. Présente dès ''The Philosophy of Philosophy'', en 2007, cette thèse se déploie jusqu'à ses essais d'éthique de 2025, étendue à des territoires toujours nouveaux ; c'est elle que recouvrira, de façon de plus en plus assumée, le mot d'anti-exceptionnalisme. L'une et l'autre reposent sur une conviction plus profonde : le réalisme. Il y a une manière dont les choses sont, indépendamment de ce que nous en savons. La bivalence, cette thèse sémantique selon laquelle toute proposition est vraie ou fausse, et la logique classique qui gouverne les inférences valides restent, à ses yeux, les meilleurs instruments pour traiter nos énoncés sur le monde. Non qu'elles le décriraient à la façon d'une théorie physique : elles s'imposent parce qu'elles figurent dans la meilleure théorie d'ensemble de l'inférence et de la signification. Et notre ignorance, si vaste soit-elle, ne doit jamais être confondue avec une indétermination des choses elles-mêmes. Cette distinction, banale en apparence, suffit à départager Williamson de la plupart de ses adversaires. == Les premiers travaux : identité, indiscernabilité, critères == [[Fichier:Young frege.jpg|vignette|Gottlob Frege, dont le critère d'identité des directions sert de point de départ aux premiers travaux de Williamson.]] On présente parfois l'œuvre comme si elle commençait avec le paradoxe du tas. Ce serait oublier les premiers travaux, où se forge pourtant l'outil dont toute la suite tirera parti. Dès 1986, dans un article au titre austère, « Criteria of Identity and the Axiom of Choice », puis plus amplement dans son premier livre, ''Identity and Discrimination'', paru en 1990, Williamson reprend une question que les philosophes posent depuis Frege : qu'est-ce qu'un critère d'identité<ref>« Criteria of Identity and the Axiom of Choice », ''The Journal of Philosophy'', vol. 83, n° 7, 1986, p. 380-394 ; ''Identity and Discrimination'', Oxford, Basil Blackwell, 1990. L'analyse établit que, lorsque la relation de base est réflexive, symétrique mais non transitive, aucune relation n'obéit à la contrainte « forte » d'un critère d'identité, et que plusieurs y obéissent au sens « faible », l'existence d'un tel critère étant équivalente à l'axiome du choix.</ref> ? Frege en avait donné l'exemple canonique. Pour penser la direction d'une droite, disait-il, il faut d'abord savoir ce que c'est, pour deux droites, que d'être parallèles : la direction de la droite ''a'' est identique à la direction de la droite ''b'' si et seulement si ''a'' et ''b'' sont parallèles. Un critère d'identité, c'est cela : une relation entre des objets de départ, ici les droites, qui fixe l'identité d'objets dérivés, ici les directions. Et pour faire ce travail, la relation doit posséder une forme bien précise, celle des relations d'équivalence : réflexive, symétrique et transitive, à l'image de l'identité elle-même. Or Williamson met le doigt sur un cas où le candidat le plus naturel échoue à remplir cette condition. Cherchons un critère d'identité pour la couleur perçue. La relation qui s'impose est l'indiscernabilité : deux échantillons ont la même couleur perçue lorsque l'œil ne parvient pas à les distinguer. Mais cette relation a un défaut qui la disqualifie : elle n'est pas transitive. Un premier échantillon peut être indiscernable d'un deuxième, le deuxième d'un troisième, et le premier se distinguer pourtant nettement du troisième ; de minuscules écarts, insensibles un à un, finissent par s'additionner. L'indiscernabilité ne peut donc pas tenir lieu de critère d'identité, puisqu'un critère doit être transitif et qu'elle ne l'est pas. La suite de l'analyse est d'une grande technicité, et c'est là qu'intervient l'axiome du choix, ce principe de la théorie des ensembles qui autorise à prélever un élément dans chacun des membres d'une collection, fût-elle infinie. Williamson démontre un résultat en deux volets. Là où la relation de départ n'est pas transitive, aucune relation ne peut servir de critère d'identité au sens fort ; et si l'on se contente d'un critère au sens faible, l'axiome du choix garantit qu'il en existe, mais plusieurs à la fois, sans qu'aucun ait un meilleur titre que les autres à passer pour le bon. Mieux, l'hypothèse même qu'un tel critère existe toujours s'avère équivalente à l'axiome du choix. La conséquence inquiète notre confiance ordinaire dans l'identité : partout où la transitivité de l'indiscernabilité se brise, nos jugements d'identité perçue perdent toute valeur de vérité déterminée, et le concept lui-même menace de n'être pas bien défini. Williamson illustre la même structure par l'identité personnelle, par ces cas de fission où une personne se scinderait en deux continuateurs : auquel des deux faut-il l'identifier ? Aucune réponse ne s'impose, et le choix paraît arbitraire. Ce premier livre n'est pas un exercice isolé de logique. Il contient en germe presque tout ce qui suivra. L'idée que des différences imperceptibles s'accumulent jusqu'à devenir perceptibles, que nos capacités de discrimination sont par nature grossières, qu'il faut une certaine marge entre deux situations pour pouvoir les départager en connaissance de cause : voilà déjà le principe de marge d'erreur. Il reparaîtra au cœur de la théorie du vague, puis de la théorie de la connaissance. La structure découverte à propos des couleurs, transposée aux significations, puis aux états de connaissance, deviendra la matrice de toute l'œuvre<ref>Le lien entre l'indiscernabilité non transitive et le principe de marge d'erreur est noué dans ''Identity and Discrimination'', 1990, puis formalisé dans « Inexact Knowledge », ''Mind'', vol. 101, 1992, et dans ''Vagueness'', 1994, chap. 8 (p. 229 et suiv.). La marge d'erreur y est posée comme condition de fiabilité : une croyance ne vaut comme connaissance que si la proposition reste vraie dans tous les cas suffisamment semblables.</ref>. == Le vague et l'ignorance == [[Fichier:Color gradient illustrating a sorites paradox.png|vignette|Un dégradé continu : à partir de quelle nuance le rouge cesse-t-il d'être rouge ? L'absence de frontière visible est au cœur du sorite.]] Sa notoriété philosophique commence surtout avec un casse-tête vénérable, le sorite, du grec ''sôros'', le tas. Un seul grain de blé ne fait pas un tas ; ajouter un grain à ce qui n'est pas un tas ne saurait le transformer en tas ; donc, de proche en proche, dix mille grains ne font toujours pas un tas. La conclusion est manifestement absurde, et pourtant chacune des prémisses paraît irréprochable. Le paradoxe vaut pour tous les prédicats vagues de notre langue : « chauve », « grand », « mince », « rouge ». Combien de cheveux faut-il perdre pour devenir chauve ? À quel instant précis l'enfant que nous fûmes a-t-il cessé d'être un enfant ? Ces questions semblent n'admettre aucune réponse, et c'est cette absence apparente de frontière nette qui paraît constituer le vague lui-même. Le premier tiers de ''Vagueness'' est d'ailleurs une histoire, conduite avec une érudition que l'on n'attend pas toujours d'un logicien<ref>''Vagueness'', chap. 1, pour l'histoire du paradoxe, de Chrysippe à Frege et Russell.</ref>. Williamson y exhume la longue carrière du paradoxe, depuis les Mégariques qui l'inventèrent jusqu'aux logiciens modernes qui le redécouvrirent. Il s'attarde sur la réponse de Chrysippe le stoïcien, qui se taisait avant la question embarrassante, comme un cocher retient ses chevaux au bord du précipice, et il note que les stoïciens, loin de nier l'existence d'une coupure nette, l'acceptaient au contraire de bon cœur. Il rappelle que Leibniz, répondant à Locke, discutait déjà du Tas et du Chauve, que Hegel se servait du sorite pour illustrer le passage du quantitatif au qualitatif, l'eau qui se change soudain en vapeur ou en glace. Avec Frege et Russell, le vague redevient une menace pour la logique : Frege le bannissait comme un défaut du langage ordinaire, Russell le rattachait à la non-transitivité de l'indiscernabilité et au seuil de la discrimination. En reconstruisant cette tradition, Williamson ne fait pas seulement œuvre d'historien : il montre que sa propre solution, l'idée d'une frontière nette mais cachée, a des ancêtres, et qu'elle est moins extravagante qu'elle n'en a l'air. Trois grandes stratégies se partageaient le terrain lorsque Williamson publie ''Vagueness'', en 1994. La première, issue des logiques à valeurs multiples, propose de remplacer le couple vrai-faux par un continuum de degrés de vérité : « Il est chauve » serait vrai à 0,6, ni tout à fait vrai ni tout à fait faux. La deuxième, la méthode des survaluations, conserve le vrai et le faux mais admet que certaines propositions n'ont aucune valeur de vérité dans les cas limites ; une phrase ne devient vraie que si elle l'est sous toutes les façons admissibles de rendre le terme précis. La troisième, le nihilisme, conclut du paradoxe que les prédicats vagues sont tout simplement incohérents, qu'il n'y a ni tas ni chauves. Williamson examine ces trois voies avec une patience d'horloger, et les écarte l'une après l'autre, parce que toutes paient leur solution d'un sacrifice : elles renoncent à la logique classique, ou à la bivalence, ou aux choses mêmes. La thèse qu'il leur substitue déconcerte au premier abord, et il ne s'en cache pas. Sa préface s'ouvre sur un aveu : ce livre, écrit-il, est né de ses tentatives pour réfuter sa propre thèse principale, à savoir que le vague consiste dans notre ignorance des frontières nettes de nos concepts, et qu'il n'exige donc aucune révision de la logique standard<ref>La préface de ''Vagueness'' présente le livre comme né de tentatives pour réfuter la thèse épistémique : le vague consiste dans notre ignorance des frontières nettes de nos concepts.</ref>. L'idée est la suivante. Il existe bel et bien un nombre de cheveux à partir duquel on est chauve : un homme avec ce nombre de cheveux est chauve, un homme avec un cheveu de plus ne l'est pas. La coupure existe, mais nous ne pouvons savoir où elle passe. Le vague n'est pas une propriété du monde, une indétermination des faits ; c'est une variété particulière de notre ignorance. Cette position, que l'on nomme aujourd'hui épistémicisme, permet de tout conserver : la bivalence, le tiers exclu, la logique classique dans son intégrité. Le sorite est alors résolu : sa prémisse inductive, l'idée qu'un grain de plus ne fait jamais la différence, est tout bonnement fausse, car il existe bel et bien un grain qui la fait, même si nous ignorons lequel. Williamson ne nie pourtant pas que nos mots soient vagues : c'est même cette vagueur qu'il entreprend d'expliquer, et son originalité tient à ce qu'il en propose une théorie, qui l'identifie à une ignorance plutôt qu'à un flou des choses. Reste alors l'objection qui vient aussitôt à l'esprit, et qui faisait jusque-là figure de réfutation : si ces frontières existaient, nous devrions pouvoir les trouver ; or nous ne le pouvons pas ; donc elles n'existent pas. Tout l'effort du livre consiste à désamorcer ce raisonnement en expliquant pourquoi, si elles existaient, elles nous demeureraient par principe inaccessibles. L'explication mobilise deux ressorts. Le premier est la manière dont le sens d'un mot dépend de l'usage que nous en faisons collectivement. La signification de « mince » est fixée par l'immense réseau de nos dispositions à l'employer ou à le refuser ; or aucun de nous ne peut surveiller ce réseau dans tous ses détails, ni rendre l'usage qu'il fait du mot à un instant donné parfaitement sensible à l'ensemble dont il dépend. Le second ressort est la marge d'erreur. Williamson le montre par un exemple où il se prend lui-même pour cobaye. La phrase « TW est mince » est peut-être vraie, mais elle aurait très facilement pu être fausse, sans que ses mensurations changent d'un pouce, pour peu que l'usage du mot « mince » eût été tant soit peu différent, ce qui était parfaitement possible. Et celui qui prononce assertivement cette phrase aurait tout aussi facilement pu la prononcer à faux, car sa décision de l'énoncer n'était pas sensible à tous les menus déplacements d'usage qui l'auraient rendue fausse. Une croyance ne vaut comme connaissance que si elle n'aurait pas pu se tromper aussi aisément. Près de la frontière, cette condition n'est jamais remplie, et notre ignorance n'y est donc pas accidentelle, mais structurelle. On reconnaît ici, transposé des couleurs aux significations, le mécanisme étudié dans ''Identity and Discrimination''. Un mot vague est entouré d'autres significations possibles, infinitésimalement proches, que ceux qui les manieraient ne sauraient distinguer de la sienne ; et c'est cette indiscernabilité des sens voisins qui nous voile la frontière. La théorie du vague rejoint enfin l'épistémologie par un autre biais, celui du principe que les logiciens écrivent KK : si l'on sait quelque chose, sait-on que l'on le sait ? Williamson répond non. Reprenons l'exemple de l'arbre devant lequel il passe presque chaque jour depuis des années, sans jamais le mesurer. Sa connaissance de la hauteur de cet arbre est inexacte : sa vue, sa mémoire, son sens des proportions sont imparfaits. On peut construire un modèle où la relation entre situations compatibles avec ce que l'on sait n'est pas transitive, exactement comme l'indiscernabilité des hauteurs ; et le principe KK s'y effondre : on peut savoir sans pour autant savoir que l'on sait. Le sorite ne menace donc pas le prédicat « tas » ; il menacerait, tout au plus, le prédicat « tas connu », et seulement si l'on acceptait KK. Sans ce principe, une itération de savoir se perd à chaque pas, et le paradoxe s'épuise avant d'atteindre sa conclusion fausse<ref>« Inexact Knowledge », ''Mind'', 1992, p. 237-238, et ''Vagueness'', 1994, chap. 8 : le diagnostic du sorite pour la connaissance procède en niant le principe KK, lui-même conséquence du principe de marge d'erreur. L'analyse est reprise dans ''Knowledge and Its Limits'', 2000, chap. 4-5.</ref>. == La connaissance d'abord == Pendant un demi-siècle, l'épistémologie de langue anglaise a tourné autour d'un projet : analyser la connaissance, c'est-à-dire la décomposer en éléments plus simples. La formule héritée de Platon en donnait la première version : connaître, ce serait croire quelque chose de vrai et de justifié. En 1963, un article de trois pages d'Edmund Gettier ruina cette définition par deux contre-exemples, et ouvrit une longue chasse à la condition manquante qui réparerait la formule<ref>Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, 1963, p. 121-123.</ref>. Toutes les tentatives échouèrent, chacune appelant un nouveau contre-exemple. Williamson propose alors de renverser l'ordre des priorités : et si la connaissance ne se laissait pas analyser, parce qu'elle était première ? Il s'agit d'un renversement plutôt que d'une abolition : Williamson ne prétend pas clore une fois pour toutes le projet d'analyse de la connaissance, mais il en inverse la direction et propose d'en faire l'économie. Au lieu de tenir la connaissance pour un composé de croyance, de vérité et d'on ne sait quel ingrédient supplémentaire, il en fait le point de départ, le concept à l'aide duquel on éclaire les autres. ''Knowledge and Its Limits'', paru en 2000, porte ce programme : la connaissance d'abord, ''knowledge first''. La connaissance y est présentée comme un état mental à part entière, et même comme l'état mental factif le plus général, celui qui chapeaute toute la famille des attitudes qui ne peuvent porter que sur du vrai<ref>''Knowledge and Its Limits'', Oxford, Oxford University Press, 2000, chap. 1 : la connaissance est un état mental factif, et le plus général d'entre eux, en ce sens que tout état factif implique la connaissance de son contenu.</ref>. Voir que la porte est ouverte, se souvenir qu'on l'a fermée, s'apercevoir qu'il pleut : autant d'états qui enveloppent la vérité de leur contenu, et qui sont, chacun, une manière de savoir. On ne définit pas la connaissance ; on la situe, au sommet de cette famille. Si Williamson tient tant à cette indécomposabilité, qu'il nomme la primalité, c'est que la connaissance explique ce que la simple croyance n'explique pas. Il en donne un exemple resté célèbre, celui du cambrioleur. Un voleur qui sait qu'un diamant se trouve dans la maison la fouillera toute la nuit, sans se décourager ; celui qui le croit seulement, même avec raison et de bon droit, risque d'abandonner plus tôt, parce que sa relation au fait est plus fragile. La connaissance, attache plus solide au monde, soutient l'action avec une constance que la croyance n'a pas. Or si l'on décompose le savoir en un noyau interne, la croyance, et un supplément externe, la vérité plus quelque garantie, on perd cette unité explicative : l'explication renvoie à la connaissance prise en bloc, non à une conjonction de deux facteurs indépendants. À cet état premier, Williamson refuse une propriété que la tradition lui prêtait volontiers : la transparence, ou comme il dit la luminosité. Une condition est lumineuse si, dès qu'elle est remplie, on est en position de savoir qu'elle l'est. On a longtemps cru que nos propres états d'esprit étaient ainsi faits, qu'il suffisait d'éprouver une douleur ou de sentir le froid pour savoir qu'on les éprouve. Williamson construit contre cette idée un argument serré, fondé une fois encore sur la marge d'erreur<ref>''Knowledge and Its Limits'', chap. 4 et 5, pour l'argument contre la luminosité et la notion de sécurité (''safety'').</ref>. La conséquence est une réfutation du principe KK déjà rencontré à propos du vague : on peut savoir sans savoir que l'on sait, parce que la connaissance exige une marge de sécurité, la sécurité que l'on n'aurait pas pu aisément se tromper. Cette notion de sécurité fournit d'ailleurs la caractérisation positive du savoir que Williamson est prêt à concéder, non comme une analyse, mais comme une vérité éclairante : si l'on sait, on n'aurait pas pu facilement avoir tort dans un cas semblable. Une croyance est sûre lorsque, dans tous les cas suffisamment proches où on la formerait sur une base semblable, elle serait vraie. La sécurité n'est pas une condition interne ; elle dépend de la configuration du monde autour de nous. C'est dire combien l'épistémologie de Williamson tourne le dos à l'internalisme, à l'idée que tout ce qui compte pour la justification serait accessible par simple réflexion. La connaissance habite le monde, non l'intériorité d'un sujet replié sur ses états. De ce primat de la connaissance, Williamson tire une dernière conséquence, qui a fait couler beaucoup d'encre : notre évidence se réduit à ce que nous savons<ref>''Knowledge and Its Limits'', chap. 9 : l'évidence est la connaissance (''E = K'').</ref>. ''E = K'', écrit-il, l'évidence est la connaissance. Ce dont nous disposons pour étayer nos croyances, ce sur quoi nous raisonnons, n'est ni un donné sensoriel ni un ensemble d'impressions privées, mais l'ensemble des propositions que nous connaissons. Le foyer cognitif cartésien, ce lieu intérieur où l'esprit serait chez lui et ne pourrait se tromper, est un mythe : il n'y a pas de retraite à l'abri du monde. Cette thèse demeure l'une des plus débattues de l'épistémologie récente, et l'article ne lui rendrait pas justice en la présentant comme un acquis. Les internalistes lui reprochent de congédier trop vite l'idée d'une justification accessible de l'intérieur ; les partisans d'une théorie de la justification refusent de renoncer au projet d'analyse ; d'autres contestent que l'on puisse traiter la connaissance comme un état mental factif primitif. Ernest Sosa, par exemple, a objecté que « croire sûrement » serait un état factif plus général que la connaissance, ce qui ruinerait la caractérisation ; Williamson a répliqué que « croire sûrement » n'est pas sémantiquement insécable, et ne saurait donc compter parmi les états factifs primitifs. Le débat n'est pas clos ; il a seulement changé de terrain, ce qui est peut-être la meilleure mesure de l'influence du livre. == La modalité : du possible imaginé au possible réel == La modalité, ce domaine du nécessaire et du possible, occupe Williamson sous deux aspects qu'il importe de ne pas confondre : comment connaissons-nous ce qui aurait pu être, et qu'est-ce, au juste, qui aurait pu être ? La première question est épistémologique, la seconde métaphysique, et il leur a donné des réponses également originales. Sur la connaissance du possible, la conception reçue voulait que nous disposions d'une faculté propre, la conception ou ''conceivability'', qui ferait office de fenêtre sur le possible : ce que je puis concevoir sans contradiction serait possible, ce que je ne puis concevoir serait impossible. Williamson récuse cette image d'une faculté spéciale. Notre savoir des possibilités, soutient-il dans ''The Philosophy of Philosophy'', fait appel à la même aptitude tout ordinaire qui nous sert à évaluer des conditionnels contrefactuels, ces énoncés en « si... alors il en serait allé ainsi » que nous manions à longueur de journée<ref>''The Philosophy of Philosophy'', Oxford, Blackwell, 2007, chap. 5 : la connaissance modale fait appel à la même capacité cognitive que l'évaluation des conditionnels contrefactuels, sans qu'il faille postuler une faculté supplémentaire.</ref>. Pour décider si quelque chose aurait pu se produire, nous développons l'hypothèse et regardons si une contradiction en surgit, exactement comme lorsque nous nous demandons ce qui serait arrivé si nous avions pris l'autre chemin. Or cette aptitude n'a rien d'a priori au sens traditionnel : elle puise abondamment dans notre connaissance du monde, elle est faillible, elle n'est pas transparente. On ne lit pas le possible dans le ciel des idées ; on l'établit, avec les moyens du bord, à partir de ce que l'on sait déjà. Du même coup, les démarches qui prétendent s'appuyer sur un a priori bien net, comme la sémantique à deux dimensions chère à [[Dictionnaire de philosophie/David Chalmers|David Chalmers]], se trouvent fragilisées dans leurs fondements épistémiques<ref>« Armchair Philosophy, Metaphysical Modality and Counterfactual Thinking », ''Proceedings of the Aristotelian Society'', vol. 105, 2005, p. 1-23, et ''The Philosophy of Philosophy'', 2007, chap. 5. La concevabilité y est tenue pour un test peu fiable du possible tant qu'on ne la définit pas par la possibilité même ; l'aptitude réellement à l'œuvre est celle, ordinaire, qui sert à évaluer les conditionnels contrefactuels, de sorte qu'aucune faculté spéciale n'a besoin d'être postulée.</ref>. Reste la seconde question, proprement métaphysique : qu'est-ce qui aurait pu être ? Ici Williamson défend, dans ''Modal Logic as Metaphysics'' (2013), une thèse qu'il nomme le nécessitisme, et qui heurte de front le sens commun. On peut l'énoncer en une formule : nécessairement, tout est nécessairement quelque chose<ref>''Modal Logic as Metaphysics'', Oxford, Oxford University Press, 2013, chap. 1 ; et « Necessitism, Contingentism, and Plural Quantification », ''Mind'', vol. 119, n° 475, 2010, p. 657-748, qui formule la thèse (NNE : nécessairement, tout est nécessairement quelque chose) et la distingue du possibilisme comme du meinongianisme. Le terme retenu pour les objets en question est « contingentement non concret » et non « seulement possible ».</ref>. Autrement dit, rien de ce qui est ne pourrait n'avoir absolument rien été ; et rien, non plus, ne pourrait s'ajouter à ce qu'il y a. Le contingentiste, son adversaire, soutient l'inverse : telle table existe, mais aurait pu n'exister pas du tout, et d'autres choses auraient pu exister qui n'existent pas. Une objection se présente aussitôt : si rien ne peut commencer ni cesser d'être quelque chose, que faire de l'enfant que tel couple aurait pu avoir et n'a pas eu, de la table que ce menuisier aurait pu fabriquer et n'a pas fabriquée ? Ce serait pourtant caricaturer la thèse : le nécessitiste ne dit pas qu'il existe, à côté des choses concrètes, une foule de fantômes seulement possibles. Ce que nous sommes tentés d'appeler un « objet seulement possible », par exemple un enfant possible de Wittgenstein, est en réalité un objet contingentement non concret : il est bel et bien quelque chose, il aurait pu être concret, de chair et d'os, mais il se trouve qu'il ne l'est pas. Il n'est pas un néant, ni un possible flottant entre l'être et le non-être ; il est, sur le mode du non-concret. Williamson prend soin de distinguer cette position de deux autres avec lesquelles on la confond aisément : elle n'est pas le meinongianisme, qui peuplerait le monde d'objets inexistants ; elle n'est pas davantage le possibilisme classique. Le débat embrouillé entre possibilistes et actualistes se laisse, dit-il, reformuler en un débat plus clair et plus maniable, celui du nécessitisme et du [[Dictionnaire de philosophie/Contingence|contingentisme]], qui se joue sur la validité d'une formule logique précise, la formule de Barcan. Si Williamson soutient une thèse aussi contre-intuitive, ce n'est pas par goût du paradoxe, mais par fidélité à sa méthode. Le nécessitisme, montre-t-il, fournit la logique modale quantifiée la plus simple et la plus puissante : il valide la formule de Barcan et sa réciproque, il autorise une sémantique à domaine constant, il évite une foule de complications. Entre deux théories rivales, on choisit comme le physicien choisit entre deux hypothèses : celle qui rend le plus avec le moins. Que la plus simple heurte nos intuitions n'est pas, en soi, un argument contre elle ; nos intuitions sur ce qui aurait pu exister n'ont pas plus d'autorité, sur ce terrain, que le sens commun n'en avait sur la mécanique céleste. == La méthode : l'anti-exceptionnalisme == Tous ces résultats reposent sur une même conception de ce qu'est philosopher, exposée dans ''The Philosophy of Philosophy'' (2007) puis, sous une forme accessible à tous, dans ''Doing Philosophy'' (2018). La thèse y est déjà nette, même si le mot ne s'imposera vraiment que plus tard : c'est ce qu'il appellera, et de plus en plus explicitement, anti-exceptionnalisme<ref>''The Philosophy of Philosophy'', chap. 1 et 7 ; ''Doing Philosophy'', Oxford, Oxford University Press, 2018. La thèse méthodologique est présente dès 2007 ; le qualificatif « anti-exceptionnaliste » ne devient un mot d'ordre explicite que dans les travaux plus récents, du sous-titre de ''Good as Usual'' (2025) à des essais comme « Moral Anti-Exceptionalism ».</ref>. La philosophie, soutient-il, n'occupe aucune position d'exception parmi les savoirs. Elle ne dispose pas d'une faculté spéciale qui lui ouvrirait un accès direct aux essences ; elle ne procède pas par une méthode purement a priori qui la couperait de l'expérience. Elle est de la même famille que les autres enquêtes, simplement plus abstraite et privée de laboratoire. Le cas le plus discuté est celui des intuitions. On répète volontiers que la philosophie se fonde sur des intuitions, ces jugements spontanés que provoquent en nous les expériences de pensée : le wagon fou que l'on peut dévier sur une autre voie, la chambre chinoise, le village où l'on ne sait plus qui est chauve. Williamson conteste cette description. Ce que nous appelons intuition n'est pas le verdict d'une faculté mystérieuse, ni un donné qu'il faudrait recueillir comme on recueille des réponses à un sondage. C'est un simple jugement, exercé sur un cas hypothétique, et il vaut comme source de connaissance pour autant qu'il est compétent, non parce qu'il serait « intuitif ». La même capacité ordinaire d'évaluer des conditionnels contrefactuels, déjà rencontrée à propos du possible, suffit à en rendre compte : juger ce qui se passerait si telle situation se présentait, voilà ce que nous faisons devant une expérience de pensée, et c'est une chose que nous savons faire. De là une conséquence qui dérange les habitudes : la distinction même de l'a priori et de l'a posteriori, sur laquelle tant de débats se sont bâtis, lui paraît trop grossière pour un travail théorique sérieux. Nos connaissances modales, par exemple, ne sont ni purement indépendantes de l'expérience ni purement tirées d'elle ; l'expérience y joue un rôle qui n'est ni de simple justification ni de simple déclenchement, de sorte que la frontière elle-même s'estompe. Une question philosophique se tranche alors par la même méthode que partout : l'inférence vers la meilleure explication, ce que la tradition nomme l'[[Dictionnaire de philosophie/Abduction|abduction]]. On compare des théories rivales, on pèse leur simplicité, leur puissance, leur accord avec ce que l'on tient par ailleurs pour acquis, et l'on retient la meilleure. Rien, en philosophie, n'est gratuit au point de n'imposer aucune contrainte à la réalité : une thèse a des conséquences, et ses conséquences se paient. C'est cette conception qui commande, chaque fois, les choix de Williamson, du nécessitisme à la défense de la logique classique. La question n'est jamais « qu'est-ce qui est évident ? », mais « quelle théorie d'ensemble fait le mieux le travail ? ». == Le dialogue : ''Tetralogue'' == ''Tetralogue'', paru en 2015, est un dialogue à la manière antique : quatre voyageurs se trouvent réunis dans un train et discutent jusqu'au terminus. Sarah défend la science et la raison ; Bob, qu'un guérisseur a guéri, en est venu à croire à la sorcellerie ; Roxana, logicienne intransigeante, traque la moindre incohérence ; Zac, conciliant et relativiste, voudrait que chacun ait raison à sa façon. De ce quatuor naît une comédie d'idées où s'affrontent les attitudes que nous adoptons spontanément face au désaccord. Le propos du livre est de défendre, sans pédantisme, deux thèses jumelles que Williamson tient pour inséparables : la vérité est objective, et nous sommes faillibles. Contre Zac, il s'agit de montrer que la formule « vrai pour moi » ne veut rien dire de cohérent : si une chose est vraie, elle l'est tout court, et croire le contraire à propos du même monde, c'est se tromper, non détenir une autre vérité. Contre une certaine arrogance scientiste, il s'agit de rappeler que reconnaître la possibilité de son erreur n'oblige nullement à renoncer à juger. Le titre, ''I'm Right, You're Wrong'', condense cette double leçon avec une provocation calculée : dans un désaccord véritable, l'un a raison et l'autre tort, et l'admettre n'est pas un manque de tolérance, c'est la condition d'une conversation sérieuse. On respecte mieux autrui en le tenant pour capable de vérité et d'erreur qu'en le confinant poliment dans sa bulle. Le dialogue, sous ses dehors plaisants, est ainsi une défense du réalisme contre le relativisme, ce même réalisme qui gouverne en sous-main toute l'œuvre. == L'éthique et l'action : ''Good as Usual'' == Le dernier grand chantier de Williamson, rassemblé en 2025 sous le titre ''Good as Usual'', dont le sous-titre annonce des essais anti-exceptionnalistes sur les normes, les valeurs et l'action, étend à la philosophie pratique le programme élaboré ailleurs. La thèse directrice est que le normatif ne forme pas un royaume à part. Le bien, la connaissance morale, les normes de la croyance et de l'action ne sont pas plus exceptionnels que le reste ; ils s'étudient avec les mêmes outils, et la connaissance y joue le même rôle central que dans la vie intellectuelle. Prenons d'abord la connaissance morale. Contre l'argument sceptique qui invoque l'ampleur des désaccords moraux pour conclure à l'absence de savoir éthique, Williamson rappelle que la connaissance n'exige qu'une fiabilité locale. Pourvu que l'on admette qu'il y a des vérités morales, il n'y a, soutient-il, aucun obstacle particulier à les connaître. Que des sociétés divergent sur ce qui est juste ne prouve pas que nul ne sait rien en morale, pas plus que l'existence de désaccords perceptifs ne ruine la perception ; on peut être fiable touchant les actions de son propre milieu sans l'être touchant celles d'un milieu lointain. La capacité de reconnaître le bien et le mal est une capacité de reconnaissance comme une autre, faillible et néanmoins source de savoir. Ensuite, la connaissance d'abord s'applique à l'action, et c'est ici qu'il faut restituer exactement les termes de l'analogie, qu'on déforme facilement. Connaître se tient à croire comme produire intentionnellement un état de choses se tient à le désirer<ref>L'analogie remonte à « Knowing and Asserting », ''The Philosophical Review'', vol. 105, n° 4, 1996, p. 489-523 (notamment p. 521) : connaître se tient à croire comme produire intentionnellement un état de choses se tient à le désirer ; les deux assurent l'accord du contenu et du monde, mais selon des directions d'ajustement opposées. Elle est reprise et développée dans ''Good as Usual'', 2025.</ref>. Si je sais que P, alors P ; de même, si je fais en sorte que P, alors P. Mais il ne suffit pas, pour savoir que P, de le croire alors que P se trouve vrai, car l'accord pourrait n'être qu'accidentel ; il ne suffit pas davantage, pour avoir produit P, de l'avoir désiré alors que P se trouve réalisé. La connaissance est le bon cas d'une direction d'ajustement, celle de l'esprit au monde : la croyance vise à se conformer au monde, et la connaissance est la croyance qui y parvient sans hasard. L'action est le bon cas de la direction inverse, celle du monde à l'esprit : le désir vise à conformer le monde à lui, et l'action est le désir qui y parvient sans hasard. Ce qui sépare connaissance et action n'est donc pas le degré de réussite, c'est le sens de l'ajustement. La connaissance est l'entrée du raisonnement pratique, son point de départ ; l'action en est la sortie réussie. De là une norme symétrique de celle de l'assertion : n'agis que sur ce que tu sais. Quand la délibération fonctionne bien, on n'emploie comme prémisse que ce que l'on connaît ; une prémisse simplement crue, sans être sue, est un grain de sable qui dérègle la machine. Williamson y intègre une thèse qu'il défend de longue date avec Jason Stanley, l'intellectualisme touchant le savoir-faire : savoir faire quelque chose, c'est savoir une vérité, et non posséder une aptitude d'une autre nature ; le savoir-faire peut donc fournir une prémisse au raisonnement pratique précisément parce qu'il est un savoir-que. Le même esprit conduit Williamson à reprendre, du côté de la croyance, sa critique de l'internalisme. Il existe plusieurs normes possibles de la croyance : une norme de vérité, une norme d'évidence, une norme de connaissance. Il plaide pour la dernière, sous une forme fonctionnelle : crois seulement ce que tu sais. Et il fait jouer une dernière fois l'argument contre la luminosité pour récuser l'exigence internaliste selon laquelle les fondements de nos jugements devraient nous être accessibles par simple introspection. Le titre du recueil joue d'ailleurs sur les mots : le bien y est traité « comme d'habitude », c'est-à-dire comme le fonctionnement normal, non défectueux, d'êtres engagés dans le monde. Là encore, le geste de Williamson est de ramener la valeur dans le tissu commun de la connaissance et de l'action, au lieu de la reléguer dans une sphère séparée. == Réception et influence == L'œuvre de Williamson a suscité une littérature critique abondante, signe de son importance. Deux volumes collectifs lui ont été consacrés, l'un sur la connaissance, l'autre sur la modalité, chacun accompagné de ses réponses détaillées aux objections<ref>Patrick Greenough et Duncan Pritchard (dir.), ''Williamson on Knowledge'', 2009 ; Mark McCullagh et Juhani Yli-Vakkuri (dir.), ''Williamson on Modality'', 2017.</ref>. Les fronts de discussion sont nombreux. Les internalistes tiennent qu'il a écarté trop vite l'idée d'une justification accessible de l'intérieur. Les défenseurs de la méthode des survaluations, comme Delia Graff Fara, refusent de payer la bivalence au prix de l'intuition qu'aucune coupure nette ne traverse nos prédicats vagues. Les partisans des logiques non classiques rejettent son plaidoyer pour la logique standard. Certains critiques jugent le nécessitisme, avec ses objets contingentement non concrets, d'un coût métaphysique trop lourd. À chacun Williamson répond avec la même rigueur méthodique, en déplaçant le débat sur le terrain qui est le sien, celui de la comparaison des théories ; et c'est souvent cette manière de répondre, autant que les thèses elles-mêmes, qui a marqué ses lecteurs. Son influence tient aussi à autre chose qu'à ses arguments. Il a contribué à légitimer une certaine façon de faire de la philosophie : technique sans être stérile, ambitieuse sans verser dans la spéculation, attentive à la forme logique des problèmes. Son rayonnement passe enfin par l'enseignement. Il a dirigé un grand nombre de thèses, et plusieurs de ses anciens étudiants comptent aujourd'hui parmi les figures montantes de la discipline. Il s'est aussi adressé au grand public, par ses dialogues, par ses petits livres d'initiation, par ses chroniques de presse, convaincu que la philosophie n'a rien à gagner à se retrancher dans un jargon d'initiés. L'auteur de traités exigeants et le pédagogue ne font chez lui qu'une seule personne, fidèle à l'idée que la difficulté ne doit pas être masquée mais apprivoisée. == Conclusion == Ce qui frappe, au terme de ce parcours, c'est l'unité d'une œuvre que la diversité des sujets pourrait faire croire dispersée. Du vague à la connaissance, de la modalité à la méthode, et jusqu'à l'éthique des derniers travaux, une même sensibilité se reconnaît. Un réalisme constant, d'abord : le réel a ses traits indépendamment de nous, et notre ignorance ne doit jamais être prise pour une indétermination des choses. Un attachement à la logique classique, ensuite, défendu non par dogmatisme mais parce qu'elle figure dans la meilleure théorie globale. La conviction, encore, que la connaissance est la pierre angulaire, le concept premier à partir duquel s'éclairent l'évidence, l'assertion, l'action et la valeur. Et, partout, les deux mêmes orientations : la structure de la connaissance inexacte, avec son principe de marge d'erreur, née de l'indiscernabilité non transitive et reparaissant aussi bien dans la théorie du vague que dans l'argument contre la luminosité ; et l'anti-exceptionnalisme, cette idée que la philosophie ne diffère pas en nature des autres enquêtes et procède comme elles par inférence vers la meilleure explication. Williamson aura beaucoup contribué à une certaine idée de la philosophie analytique : une discipline qui traite ses questions avec autant de sérieux théorique que les sciences, sans pour autant céder à l'obscurité ni au relativisme. On peut discuter chacune de ses thèses, et beaucoup le font ; on peut juger le nécessitisme trop coûteux, l'épistémicisme trop hardi, le primat de la connaissance trop exclusif. Reste, par-delà ces désaccords, une exigence de rigueur et une manière de poser les problèmes dont la philosophie de notre temps porte l'empreinte. == Notes et références == {{références|colonnes=2}} == Bibliographie == === Sources primaires (œuvres de Timothy Williamson) === * « Criteria of Identity and the Axiom of Choice », ''The Journal of Philosophy'', vol. 83, n° 7, 1986, p. 380-394. * ''Identity and Discrimination'', Oxford, Basil Blackwell, 1990 (édition augmentée, Wiley-Blackwell, 2013). * ''Vagueness'', Londres, Routledge, 1994. * « Knowing and Asserting », ''The Philosophical Review'', vol. 105, n° 4, 1996, p. 489-523. * ''Knowledge and Its Limits'', Oxford, Oxford University Press, 2000. * ''The Philosophy of Philosophy'', Oxford, Blackwell, 2007 (2e édition augmentée, Wiley-Blackwell, 2021). * « Necessitism, Contingentism, and Plural Quantification », ''Mind'', vol. 119, n° 475, 2010, p. 657-748. * ''Modal Logic as Metaphysics'', Oxford, Oxford University Press, 2013. * ''Tetralogue: I'm Right, You're Wrong'', Oxford, Oxford University Press, 2015. * ''Doing Philosophy: From Common Curiosity to Logical Reasoning'', Oxford, Oxford University Press, 2018 (réédition en poche sous le titre ''Philosophical Method: A Very Short Introduction'', 2020). * ''Suppose and Tell: The Semantics and Heuristics of Conditionals'', Oxford, Oxford University Press, 2020. * (avec Paul Boghossian) ''Debating the A Priori'', Oxford, Oxford University Press, 2020. * ''Overfitting and Heuristics in Philosophy'', Oxford, Oxford University Press, 2024. * ''Good as Usual: Anti-Exceptionalist Essays on Norms, Values, and Action'', Oxford, Oxford University Press, 2025. === Études critiques consacrées à son œuvre === * Patrick Greenough et Duncan Pritchard (dir.), ''Williamson on Knowledge'', Oxford, Oxford University Press, 2009 (avec les « Replies to Critics » de Williamson). * Mark McCullagh et Juhani Yli-Vakkuri (dir.), ''Williamson on Modality'', Londres, Routledge, 2017. === Autres ouvrages et articles cités === * Gottlob Frege, ''Les Fondements de l'arithmétique'' (1884). * Edmund Gettier, « Is Justified True Belief Knowledge? », ''Analysis'', vol. 23, 1963, p. 121-123. * Saul Kripke, ''Naming and Necessity'', Oxford, Blackwell, 1980. * David Chalmers, ''The Conscious Mind: In Search of a Fundamental Theory'', Oxford, Oxford University Press, 1996. * Ernest Sosa, ''Knowing Full Well'', Princeton, Princeton University Press, 2011. === Sources biographiques === Les données biographiques (dates, postes, distinctions) proviennent des sources institutionnelles suivantes : * [https://www.philosophy.ox.ac.uk/people/timothy-williamson Page de Timothy Williamson, Faculty of Philosophy, université d'Oxford] * [https://www.new.ox.ac.uk/timothy-williamson Page de Timothy Williamson, New College, Oxford] * [https://www.thebritishacademy.ac.uk/fellows/timothy-williamson-FBA/ Notice « Professor Timothy Williamson FBA », The British Academy (élu Fellow en 1997)] * [https://www.rse.org.uk/fellow/timothy-williamson/ Notice « Professor Timothy Williamson FRSE », The Royal Society of Edinburgh (élu Fellow en 1997)] * [https://www.philosophy.ox.ac.uk/sitefiles/twcvshortnew-v2.pdf Curriculum vitae officiel (université d'Oxford)] == Voir aussi == * {{Page|Épistémologie}} * {{Page|Connaissance}} * {{Page|Métaphysique}} * {{Page|A priori}} * {{Page|Contingence}} * {{Page|Abduction}} * {{Page|Vérité}} * {{Page|David Chalmers}} == Sur Wikisource == Deux textes classiques évoqués dans cet article sont disponibles en texte intégral sur Wikisource : * [[s:Nouveaux Essais sur l’entendement humain|Leibniz, ''Nouveaux Essais sur l'entendement humain'']], où sont discutés le Tas et le Chauve. * [[s:Essai philosophique concernant l’entendement humain|Locke, ''Essai philosophique concernant l'entendement humain'']], dont Leibniz fait son interlocuteur. {{DEFAULTSORT:Williamson}} [[Catégorie:Dictionnaire de philosophie (livre)]] [[Catégorie:Philosophe]] g6ltkluz5xx3a3wj6x9rf49k3ghtybn Dictionnaire de philosophie/Thomas Nagel 0 83963 768455 2026-06-24T02:30:40Z PandaMystique 119061 Page créée avec « {{DicoPhilo|Thomas Nagel|lecture=oui}} [[Fichier:Thomas Nagel teaching Ethics (cropped).JPG|vignette|upright=1.1|Thomas Nagel enseignant l'éthique en 2008.]] '''Thomas Nagel''', né le 4 juillet 1937 à Belgrade, est un philosophe américain qui compte parmi les figures les plus lues de la philosophie analytique de la seconde moitié du XX{{e}}&nbsp;siècle. Son œuvre couvre la philosophie de l'esprit, l'éthique, la philosophie politique et l'Dictionnaire... » 768455 wikitext text/x-wiki {{DicoPhilo|Thomas Nagel|lecture=oui}} [[Fichier:Thomas Nagel teaching Ethics (cropped).JPG|vignette|upright=1.1|Thomas Nagel enseignant l'éthique en 2008.]] '''Thomas Nagel''', né le 4 juillet 1937 à Belgrade, est un philosophe américain qui compte parmi les figures les plus lues de la philosophie analytique de la seconde moitié du XX{{e}}&nbsp;siècle. Son œuvre couvre la philosophie de l'esprit, l'éthique, la philosophie politique et l'[[Dictionnaire de philosophie/Épistémologie|épistémologie]], et son article de 1974, « Quel effet cela fait-il d'être une chauve-souris ? », est devenu l'un des textes les plus cités du débat contemporain sur la [[Dictionnaire de philosophie/Conscience|conscience]]. Une question unique court d'un bout à l'autre de cette œuvre, et Nagel l'a formulée sans détour au seuil de son maître livre : comment concilier le point de vue d'une personne particulière, située à l'intérieur du monde, avec une conception objective de ce même monde, qui inclut cette personne et son point de vue parmi les choses qu'elle décrit<ref>Thomas Nagel, ''Le point de vue de nulle part'' [''The View from Nowhere'', 1986], trad. Sonia Kronlund, Combas, Éditions de l'éclat, 1993 (éd. originale Oxford, Oxford University Press, 1986, ci-après ''VFN''). L'énoncé du « problème unique » ouvre l'introduction (''VFN'', p.&nbsp;3).</ref>. Nous portons en nous deux regards. Le premier est celui que nous avons spontanément sur nos vies : il est ancré dans un corps, une mémoire, des désirs, un nom propre. Le second est celui que nous prenons lorsque nous nous efforçons de voir les choses telles qu'elles sont en elles-mêmes, indépendamment de la place que nous y occupons : le regard que Nagel nomme, par une formule qui a fait fortune, le point de vue de nulle part. Toute la difficulté tient à ce que ces deux regards ne se recouvrent jamais tout à fait, et que nous ne pouvons renoncer ni à l'un ni à l'autre. De cette tension Nagel a tiré une manière d'aborder presque tous les grands problèmes de la philosophie. Le rapport de l'esprit au cerveau, la possibilité de se soucier d'autrui, la peur de la mort, le sentiment de l'absurde, l'exigence d'égalité, l'autorité de la raison : chacun de ces thèmes apparaît, sous sa plume, comme une retombée du même conflit entre le dedans et le dehors. Sa thèse la plus constante est qu'il faut résister à la tentation de trancher ce conflit par un coup de force, c'est-à-dire en niant la réalité de l'un des deux points de vue. Réduire l'esprit à des processus physiques, ou réduire la morale à des préférences subjectives, revient selon lui à supprimer une part de ce qui est, par amour d'une vision unifiée. Selon lui, mieux vaut assumer cette division que la masquer. Nagel écrit une prose limpide, sobre, qui doit beaucoup à la tradition d'Oxford où il s'est formé. Il avance par exemples frappants, l'expérience de la chauve-souris, le cerveau dédoublé, le soldat qui doit choisir ses armes, et préfère poser une difficulté avec netteté plutôt que la résoudre à bon compte. Cette honnêteté à l'égard de ce qu'on ne sait pas, cette défiance envers les solutions trop commodes, donne à ses livres un ton singulier : celui d'un rationaliste qui tient la raison pour souveraine sans la croire toute-puissante. == Repères biographiques == === Un enfant de l'exil === Thomas Nagel naît le 4 juillet 1937 à Belgrade, alors capitale du royaume de Yougoslavie. Ses parents sont des Juifs allemands qui ont fui le Reich, et la famille gagne les États-Unis en 1939, à la veille de la guerre. C'est donc en anglais, dans un pays d'accueil, que se fait toute la formation intellectuelle de l'enfant. Nagel n'a pas commenté ce point de départ, et rien n'autorise à y chercher la cause de sa pensée. Tout au plus pourrait-on y voir, à titre de simple rapprochement, un écho biographique de l'un des thèmes qui traversent son œuvre : l'attention au caractère contingent de la place que chacun occupe dans le monde. Que je sois né ici plutôt que là, dans ce corps plutôt qu'un autre, à cette époque plutôt qu'une autre, voilà des faits qui auraient pu ne pas être, et dont la pensée objective doit pourtant rendre compte. Le philosophe qui demandera comment loger le fait « je suis telle personne » dans une image du monde où nulle personne n'occupe de position privilégiée pose une question dont sa propre histoire offre, par coïncidence et non par nécessité, une illustration. === Cornell, Oxford, Harvard === Nagel obtient son ''bachelor'' à l'université Cornell en 1958. Il y rencontre l'influence de Ludwig Wittgenstein, dont les idées circulent par l'intermédiaire de Norman Malcolm, et celle de la philosophie du langage ordinaire. Il poursuit ses études à Oxford, où il obtient le B.Phil. (''Bachelor of Philosophy'') en 1960. L'Oxford de ces années est dominée par John Langshaw Austin et par une méthode qui scrute les usages du langage pour dissoudre les faux problèmes ; Nagel en retient le goût de la précision et de l'argument serré, mais non la conviction que la philosophie se ramène à une thérapeutique du langage. Très tôt, il pense au contraire que certaines perplexités, sur la liberté, sur la connaissance, sur le sens de la vie, ne reposent sur aucune confusion verbale et résistent à toute dissolution<ref>Nagel revient sur ce désaccord avec l'Oxford des années 1960 dans plusieurs textes ; voir l'introduction de ''VFN'', éd. citée, p.&nbsp;11 et suivantes, où il refuse l'espoir d'une « pureté » kantienne ou wittgensteinienne qui résoudrait les problèmes en évitant certains pas de travers dans l'emploi du langage.</ref>. Il achève sa formation à Harvard, où il soutient en 1963 une thèse de doctorat dirigée par John Rawls. La rencontre est importante. Rawls travaille alors à la ''Théorie de la justice'' qui paraîtra en 1971, et il transmet à son élève une conviction qui marquera toute son éthique : que les personnes sont distinctes les unes des autres, que cette séparation n'est pas un détail mais le fait moral premier, et qu'une doctrine qui l'ignore, comme l'utilitarisme classique lorsqu'il additionne les satisfactions de tous comme si elles appartenaient à un seul sujet, manque quelque chose d'essentiel. La thèse de Nagel, remaniée, deviendra son premier livre, ''The Possibility of Altruism'', publié en 1970. === Berkeley, Princeton, New York === Nagel enseigne d'abord à l'université de Californie à Berkeley, de 1963 à 1966, puis à Princeton, de 1966 à 1980. C'est à Princeton qu'il forme plusieurs philosophes qui compteront, parmi lesquels Susan Wolf, Shelly Kagan et Samuel Scheffler, ce dernier devenu plus tard son collègue. Il y côtoie aussi Saul Kripke, dont les travaux sur la nécessité et la référence laisseront une trace dans sa philosophie de l'esprit. En 1980, il rejoint l'université de New York, où il enseigne la philosophie et le droit, et où il animera longtemps, avec le juriste Ronald Dworkin, un séminaire de philosophie politique et juridique qui fait date. Nagel reçoit plusieurs distinctions dans les années 2000 : un ''Distinguished Achievement Award'' de la fondation Mellon en 2006, le prix Rolf Schock de logique et de philosophie et le prix Balzan de philosophie morale en 2008, le prix Rescher de philosophie systématique en 2021. Oxford, Harvard et l'université de Bucarest lui décernent des doctorats honoris causa. Devenu professeur émérite, Nagel a continué de publier et d'intervenir dans le débat philosophique, notamment depuis la parution en 2012 de l'essai ''Mind and Cosmos'', qui a soulevé une controverse dépassant largement les cercles universitaires. == Le problème unique : le subjectif et l'objectif == Pour entrer dans l'œuvre de Nagel, le mieux est de partir de l'idée qui la commande, et qu'il a placée en tête du ''Point de vue de nulle part'' : son livre, écrit-il, porte sur un seul problème, celui de combiner la perspective d'une personne particulière à l'intérieur du monde avec une conception objective de ce même monde, perspective comprise<ref>''VFN'', éd. citée, p.&nbsp;3. La formule originale parle d'« a single problem ».</ref>. Ce problème n'est pas l'affaire des seuls philosophes. Il se pose à tout être doué à la fois d'un point de vue particulier et de la capacité de s'en abstraire pour concevoir le monde comme un tout. === Deux points de vue === Reprenons l'image au plus près de l'expérience. Je peux me considérer de deux façons. Je peux me considérer comme moi, du dedans : j'éprouve des douleurs et des joies, je vise des fins, je tiens à ma vie, et tout cela compte pour moi avec une force qui ne se laisse pas réduire. Mais je peux aussi me considérer du dehors, comme une personne parmi des milliards d'autres, un organisme apparu tardivement dans l'histoire d'une planète, un point minuscule dans l'espace et le temps. Ce second regard n'est pas une illusion ; il découvre des vérités, et même des vérités qui corrigent le premier. Du point de vue objectif, mon existence n'a rien de privilégié, et l'importance que j'accorde à ma propre vie apparaît comme un trait local, un effet de perspective. Le détachement, dit Nagel, est une méthode de connaissance. Pour acquérir une compréhension plus objective d'un aspect du monde, nous prenons du recul par rapport à notre vue initiale, et nous formons une nouvelle conception qui prend cette vue elle-même, et sa relation au monde, pour objet<ref>''VFN'', éd. citée, p.&nbsp;4. Nagel y définit l'objectivité comme une « méthode de compréhension » et décrit le pas en arrière par lequel l'ancienne vue devient une simple apparence, corrigible par référence à la nouvelle.</ref>. L'ancienne vue devient alors une apparence, plus subjective, que la nouvelle vient confirmer ou rectifier. Et l'opération peut se répéter, chaque pas en arrière livrant une image plus détachée, plus indépendante de notre point de départ. La science est le lieu où ce mouvement a été poussé le plus loin : elle décrit les choses non par les impressions qu'elles font sur nos sens, mais par des propriétés qu'on peut atteindre autrement que par le regard humain. === L'objectivité comme méthode et comme tentation === Voilà le ressort de la pensée objective ; voici maintenant son danger. Le mouvement de détachement est si puissant, ses succès si éclatants, qu'on est tenté de croire que tout ce qui est réel peut être saisi de cette manière, et que ce qui résiste au regard objectif n'est qu'apparence à dissiper. C'est ici que Nagel se sépare d'une bonne part de la philosophie de son temps. Il soutient que cette généralisation est une faute, et qu'elle conduit à de fausses réductions, ou au refus de reconnaître une part de ce qui est<ref>''VFN'', éd. citée, p.&nbsp;3-4 et p.&nbsp;15-17. La thèse selon laquelle « toute la réalité n'est pas mieux comprise à mesure qu'elle est vue plus objectivement » est l'un des fils du livre.</ref>. Car certaines réalités, et l'expérience consciente en est l'exemple le plus net, ne se laissent pas atteindre du dehors sans qu'on perde précisément ce qu'on voulait comprendre. Toute la réalité n'est pas mieux saisie à mesure qu'on l'envisage plus objectivement. La position de Nagel se tient ainsi sur une ligne de crête. D'un côté, il refuse le subjectivisme, pour qui notre point de vue serait la mesure de toute chose ; il croit à un monde indépendant de nous, et à des vérités que la pensée objective découvre. De l'autre, il refuse l'objectivisme, pour qui seul serait réel ce que la science peut décrire ; il maintient que le point de vue subjectif a sa part de réalité, et qu'on ne peut l'effacer sans mutiler le tableau. La sagesse, s'il en est une, consiste à juxtaposer les deux regards à pleine force, à les unifier quand c'est possible, et à reconnaître clairement les cas où ce n'est pas possible. Le reste de l'œuvre déploie cette intuition sur des terrains particuliers. == L'esprit et la conscience == Nul domaine ne montre mieux la résistance du subjectif que la conscience. C'est aussi celui où Nagel a marqué le plus durablement la discipline. === Le physicalisme et ses limites === Lorsque Nagel commence à publier, dans les années 1960, la philosophie de l'esprit anglophone est dominée par une thèse : le physicalisme, qui identifie les états mentaux à des états physiques du cerveau. Avoir mal, c'est se trouver dans un certain état neuronal ; penser, c'est l'occurrence d'un certain processus cérébral. Dès un article de 1965, justement intitulé « Physicalism », Nagel prend ses distances avec les formes naïves de cette doctrine. Il ne nie pas que les états mentaux soient liés au cerveau ; il doute que l'identité proposée rende compte de ce qu'elle prétend expliquer<ref>Thomas Nagel, « Physicalism », ''The Philosophical Review'', vol.&nbsp;74, n{{o}}&nbsp;3, 1965, p.&nbsp;339-356 (article non traduit en français).</ref>. La difficulté qu'il pressent prendra sa forme la plus célèbre près de dix ans plus tard. === Quel effet cela fait-il d'être une chauve-souris ? === L'article paraît en 1974 dans ''The Philosophical Review'', puis il est repris dans le recueil ''Mortal Questions'', traduit en français dans ''Questions mortelles''<ref>Thomas Nagel, « Quel effet cela fait-il d'être une chauve-souris ? » (« What Is It Like to Be a Bat? »), dans ''Questions mortelles'' [''Mortal Questions'', 1979], trad. Pascal Engel et Claudine Tiercelin, Paris, PUF, 1983 (éd. originale Cambridge, Cambridge University Press, 1979, ci-après ''MQ''). L'essai occupe les p.&nbsp;165-180 de l'édition anglaise ; il avait d'abord paru dans ''The Philosophical Review'', vol.&nbsp;83, n{{o}}&nbsp;4, octobre 1974, p.&nbsp;435-450.</ref>. Le titre, devenu un mot de passe de la philosophie contemporaine, énonce déjà l'idée. Nagel choisit la chauve-souris parce qu'elle est assez proche de nous pour qu'on lui accorde sans hésiter une vie consciente, et assez différente pour rendre le problème vif. La plupart des chauves-souris perçoivent le monde par sonar : elles émettent des cris à haute fréquence et lisent dans leurs échos la distance, la taille, la forme et le mouvement des objets. Ce mode de perception ne ressemble à aucun des nôtres. Posons alors la question : quel effet cela fait-il d'être une chauve-souris ? Nagel soutient que nous ne pouvons pas le savoir, et qu'il y a là un fait que notre nature nous interdit d'atteindre. Je peux bien imaginer que j'ai des membranes aux bras, que je chasse des insectes la bouche ouverte au crépuscule, que je passe le jour suspendu la tête en bas. Mais cet exercice ne me dit que ce que cela ferait, à moi, de me conduire comme une chauve-souris. Or la question n'est pas là. Je veux savoir ce que cela fait à une chauve-souris d'être une chauve-souris, et pour cela les ressources de mon esprit ne suffisent pas<ref>« Quel effet cela fait-il d'être une chauve-souris ? », dans ''MQ'', éd. citée. L'argument de l'imagination, qui distingue « ce que cela me ferait de me comporter en chauve-souris » de « ce que cela fait à la chauve-souris d'en être une », se trouve aux p.&nbsp;168-169 de l'édition anglaise.</ref>. L'imagination travaille à partir de notre propre expérience ; sa portée est par là même bornée. Que cette barrière nous arrête ne prouve pourtant pas que le fait n'existe pas. Nagel insiste sur ce renversement : nous sommes, devant la chauve-souris, dans la position où se trouveraient des chauves-souris intelligentes, ou des Martiens, s'ils essayaient de concevoir ce que c'est que d'être nous. La structure de leur esprit pourrait leur interdire d'y parvenir, mais ils auraient tort d'en conclure que rien de précis ne caractérise notre expérience, puisque nous, nous le savons<ref>« Quel effet cela fait-il d'être une chauve-souris ? », dans ''MQ'', éd. citée, p.&nbsp;170. Le renversement des chauves-souris ou Martiens essayant de concevoir l'expérience humaine sert à montrer qu'une limite de l'imagination ne vaut pas preuve d'inexistence.</ref>. Il y a donc des faits réels sur l'expérience d'un être qui échappent par principe à qui ne partage pas son point de vue. === Le caractère subjectif de l'expérience === L'exemple n'était qu'un moyen ; la thèse qu'il sert concerne la conscience en général. Ce que l'exemple met au jour, Nagel l'appelle le caractère subjectif de l'expérience : le fait qu'un organisme a des états conscients si, et seulement si, il y a un certain effet que cela fait d'être cet organisme, quelque chose que c'est pour lui<ref>« Quel effet cela fait-il d'être une chauve-souris ? », dans ''MQ'', éd. citée, p.&nbsp;166. La formule « there is something it is like to be that organism » y reçoit le nom de « subjective character of experience ».</ref>. Cette propriété, dit-il, échappe à toutes les analyses réductrices à la mode. On a tenté de définir le mental par son rôle fonctionnel, c'est-à-dire par la façon dont des états s'enchaînent entre stimulus et comportement ; mais un automate pourrait remplir ces rôles sans rien éprouver. On a tenté de le définir par ses effets sur la conduite ; mais là encore l'effet vécu manque à l'appel. Aucune de ces analyses ne touche le point sensible, parce que toutes sont compatibles avec l'absence de toute vie intérieure. Pourquoi le caractère subjectif résiste-t-il à la réduction ? Parce que, répond Nagel, tout phénomène subjectif est lié à un point de vue unique, alors qu'une théorie physique objective abandonne précisément ce point de vue<ref>« Quel effet cela fait-il d'être une chauve-souris ? », dans ''MQ'', éd. citée, p.&nbsp;167 et p.&nbsp;172-174. L'argument relie l'irréductibilité de l'expérience au fait que toute théorie physique objective procède en s'éloignant d'un point de vue particulier.</ref>. Pour d'autres réalités, le passage à l'objectif est un progrès : on comprend mieux la foudre ou l'arc-en-ciel en s'éloignant de leur apparence sensible, en les décrivant par des propriétés que même un être privé de vision pourrait saisir. L'objectivité, ici, est une direction dans laquelle l'entendement peut voyager, et il est légitime d'aller aussi loin que possible du point de vue humain. Mais l'expérience ne suit pas ce modèle. M'éloigner de mon point de vue pour comprendre ce qu'est mon expérience, ce n'est pas m'en approcher : c'est m'en éloigner. Car que resterait-il de ce que cela fait d'être une chauve-souris, si l'on retirait le point de vue de la chauve-souris ? Ce résultat, Nagel l'a souvent précisé, ne signifie pas que la conscience échappe à la science en général, mais que la science, pour en rendre compte, devrait élargir sa conception de l'objectivité au lieu de la calquer sur celle des sciences physiques<ref>Voir la préface de l'édition de 2024 du texte, où Nagel corrige un malentendu fréquent : montrer que le caractère subjectif échappe aux sciences physiques objectives n'est pas le placer hors de toute compréhension scientifique, mais appeler un élargissement de nos idées scientifiques. ''What Is It Like to Be a Bat?'', New York, Oxford University Press, 2024, ISBN&nbsp;978-0-19-775279-1 (préface).</ref>. La leçon n'est pas un renoncement, mais une mise en garde : nous ne disposons pour l'instant d'aucune idée de la manière dont une théorie physique pourrait inclure le caractère subjectif de l'expérience, et il serait léger de faire comme si le problème n'existait pas. C'est cette difficulté, longtemps refoulée, que les sciences cognitives ont peu à peu reconnue, au point que le débat sur la conscience occupe aujourd'hui une place centrale en philosophie comme en psychologie. Il importe de ne pas se méprendre sur la portée de cette critique. Nagel n'est pas dualiste : il ne soutient pas que l'esprit soit une substance séparée du corps, ni que la conscience flotte au-dessus de la matière. Sa position est plus retenue, et il l'a précisée dans ses textes ultérieurs. Il tient pour probable que les états mentaux entretiennent avec les états physiques un lien nécessaire, peut-être même une forme d'identité, mais que nous ne disposons pas encore des concepts qui permettraient de le saisir. Les expériences de pensée qui paraissent montrer qu'un organisme pourrait être physiquement identique à nous tout en étant dépourvu de toute vie intérieure, et qui semblent ainsi disjoindre le mental du physique, ne prouvent rien, selon lui, sur ce qui est réellement possible : elles trahissent seulement une lacune de nos concepts présents, incapables de relier deux ordres que nous appréhendons par des voies trop dissemblables. L'absence de connexion conceptuelle peut recouvrir une connexion nécessaire qui n'est pas encore conceptuelle, faute de nous être accessible<ref>Thomas Nagel, « Conceiving the Impossible and the Mind-Body Problem », ''Philosophy'', vol.&nbsp;73, n{{o}}&nbsp;285, juillet 1998, p.&nbsp;337-352 (article non traduit en français). Nagel y soutient que l'apparente concevabilité d'une séparation entre le mental et le physique « révèle quelque chose de nos concepts présents, mais non de ce qui est réellement possible » (p.&nbsp;346), et que l'absence de lien conceptuel peut dissimuler une « connexion nécessaire » encore inaccessible à nos concepts (p.&nbsp;345). Sur la même idée d'une unité psychophysique que nos catégories actuelles ne savent pas penser, voir ''VFN'', éd. citée, chap. III.</ref>. Loin de renoncer à l'unité du réel, Nagel l'ajourne : il attend d'une révision future de nos idées qu'elle rende intelligible ce que le matérialisme actuel postule sans le comprendre et que le dualisme abandonne trop tôt. C'est en ce sens, et non comme adversaire de la science, qu'il faut entendre son refus des réductions. Le philosophe australien [[Dictionnaire de philosophie/David Chalmers|David Chalmers]] reprendra l'intuition de Nagel pour formuler ce qu'il nomme le « problème difficile » de la conscience, tout en en tirant des conclusions plus nettement dualistes que celles de Nagel lui-même. === L'unité de la conscience et le cerveau dédoublé === Un autre texte, « Brain Bisection and the Unity of Consciousness » (1971), aborde la conscience par un biais expérimental. Pour soulager certaines épilepsies graves, les chirurgiens ont parfois sectionné le corps calleux, le faisceau de fibres qui relie les deux hémisphères du cerveau. Les patients ainsi opérés mènent une vie apparemment normale, mais des expériences soigneuses révèlent d'étranges dissociations : présenté au seul hémisphère droit, un objet peut être saisi de la main gauche sans que le sujet sache le nommer, comme si l'information disponible d'un côté restait inaccessible à l'autre<ref>Thomas Nagel, « Brain Bisection and the Unity of Consciousness », ''Synthese'', vol.&nbsp;22, 1971, p.&nbsp;396-413 ; repris dans ''MQ'', éd. citée, p.&nbsp;147-164 (« La bissection cérébrale et l'unité de la conscience » dans ''Questions mortelles''). Nagel y discute les données des patients au cerveau dédoublé.</ref>. Combien d'esprits y a-t-il dans un tel patient ? Un ? Deux ? Nagel examine plusieurs réponses et montre qu'aucune n'est satisfaisante. On ne peut dire qu'il y a deux personnes, ni vraiment une seule, ni deux esprits dans un corps, ni un esprit qui se scinde par moments. L'intérêt de l'analyse n'est pas de fournir le bon compte, mais de suggérer qu'il n'y en a peut-être aucun. Notre idée d'une conscience unifiée, d'un « je » unique qui rassemble tout ce que nous éprouvons, pourrait n'être pas une exigence de toute vie mentale concevable, mais un trait de notre cas particulier, qui se défait dès qu'on touche aux conditions physiques qui le soutiennent. Le cas du cerveau dédoublé est ainsi une fissure par où l'on voit que la première personne, ce point d'unité qui nous paraît aller de soi, dépend d'un agencement matériel et perd ses contours dès que cet agencement se modifie. La conscience, encore une fois, ne se laisse pas survoler du dehors sans que l'objet même de la question commence à se dérober. == L'éthique : la possibilité de l'altruisme == Le même conflit entre le dedans et le dehors gouverne l'éthique de Nagel, qu'il a posée dès son premier livre, ''The Possibility of Altruism''. La question qui lui donne son titre paraît simple : avons-nous des raisons de nous soucier des autres pour eux-mêmes, et non par calcul ou par sympathie passagère ? L'[[Dictionnaire de philosophie/Altruisme|altruisme]], au sens où Nagel l'entend, n'est pas un sentiment chaleureux ; c'est la disposition à agir pour le bien d'autrui parce qu'on reconnaît que ce bien fournit une raison d'agir, indépendamment de nos désirs présents. === Contre la théorie humienne du désir === L'adversaire de Nagel est une conception qu'on peut faire remonter à David Hume et qui domine encore la philosophie morale : pour qu'une considération me pousse à agir, il faudrait qu'elle s'appuie sur un désir déjà présent en moi. La raison, sur ce modèle, ne ferait que calculer les moyens ; elle serait, selon le mot fameux de Hume, l'esclave des passions. Si tel est le cas, l'altruisme devient un mystère : pourquoi le bien d'un autre me motiverait-il, si je n'ai pas d'abord le désir de l'aider ? Nagel accorde un point à cette conception. Il est exact que toute action motivée implique, en un sens, un désir : agir pour une fin, c'est être dans un certain état qu'on peut nommer désir de cette fin<ref>Le mot de Nagel, « it is a mystery how one could account for the motivational source of ethical action without referring to desires », est cité par Alan Thomas, ''Thomas Nagel'', Stocksfield, Acumen, 2009, p.&nbsp;109 (renvoyant à ''The Possibility of Altruism'', Princeton, Princeton University Press, 1978, ci-après ''PA'', p.&nbsp;4).</ref>. Mais il distingue deux sortes de désirs. Certains sont premiers : ils surgissent en moi sans raison, et c'est leur survenue qui déclenche l'action. D'autres sont motivés : ils naissent de la reconnaissance d'une raison. Quand je verse une cotisation d'assurance que je préférerais épargner, ce n'est pas qu'une envie d'assurance me saisit ; c'est que je reconnais une raison de me prémunir, et que le désir suit cette reconnaissance. La question n'est donc pas de savoir si un désir accompagne l'action, mais d'où vient ce désir : du caprice ou de la raison. === Le parallèle de la prudence === Pour faire admettre que des raisons peuvent nous mouvoir sans dériver d'un désir préalable, Nagel passe par un détour éclairant : la prudence, c'est-à-dire le souci de nos propres intérêts futurs. Reprenons l'exemple de l'assurance, qu'un commentateur a développé<ref>L'exemple de la prime d'assurance, employé pour éclairer la structure de la prudence et son analogie avec l'altruisme, est développé par Alan Thomas, ''Thomas Nagel'', éd. citée, p.&nbsp;110-111, à partir de l'argument de ''PA''.</ref>. Un défaut électrique, que j'ignore, provoquera dans dix mois un incendie qui ravagera mon logement. J'hésite, au moment de poster ma prime, parce que je convoite un téléphone neuf. Que devrais-je faire ? Tenir compte, dès aujourd'hui, d'un intérêt qui ne sera le mien que dans dix mois. Or pourquoi cet intérêt futur me donne-t-il une raison d'agir maintenant ? La réponse de Nagel touche à la structure du temps et du soi. Mon moi présent et mon moi futur ne sont pas deux personnes : ce sont des étapes d'une seule vie, qui s'étend dans le temps. Reconnaître cela, c'est reconnaître que la souffrance que j'éprouverai dans dix mois est aussi réelle que celle que j'éprouve aujourd'hui, et qu'il serait incohérent de la traiter comme négligeable au seul motif qu'elle n'est pas encore là. La prudence repose ainsi sur une vue objective de ma propre existence : je me conçois comme un être temporellement étendu, dont aucun instant n'est privilégié du seul fait qu'il est le présent. Qui nie cela tombe dans une forme de dissociation : il ne parvient plus à s'attribuer à lui-même, vu du dehors, les états qu'il s'attribue du dedans. === Le soi objectif et les raisons impersonnelles === Le pas suivant est le cœur de l'argument. Ce que la prudence fait pour le temps, l'altruisme le fait pour les personnes. De même que mon moi futur est aussi réel que mon moi présent, autrui est une personne aussi réelle que moi. Quand je me considère du point de vue objectif, je me vois comme une personne parmi d'autres, sans position privilégiée. Le fait « je suis Thomas Nagel » n'a, de ce point de vue, rien de central : c'est un fait contingent, comme le fait qu'il est telle heure ou tel jour. Mais alors mes raisons d'agir, si elles sont bien des raisons et non de simples envies, doivent valoir indépendamment de la personne que je me trouve être. Elles doivent pouvoir être reconnues par n'importe qui, et elles doivent porter sur le bien de n'importe qui<ref>''PA'', éd. citée, partie III. La thèse de l'« inescapabilité » de certaines raisons, raisons dont on ne peut « se défaire » (« beg off »), est résumée par Alan Thomas, ''Thomas Nagel'', éd. citée, p.&nbsp;110, qui y voit l'idée que certaines raisons s'appliquent à chacun indépendamment de la façon dont il se trouve motivé.</ref>. Nagel dit que certaines raisons sont inescapables : on ne peut s'en défaire en plaidant qu'elles ne nous concernent pas, parce qu'elles s'appliquent à tout le monde. L'égoïste, dès lors, occupe en pratique la position du solipsiste en théorie. Le solipsiste tient que son esprit est le seul qui existe, parce qu'il n'a un accès direct qu'au sien. L'égoïste, lui, agit comme si ses intérêts étaient les seuls à fournir des raisons, parce qu'il ne les ressent que du dedans. Tous deux refusent d'accorder aux autres la réalité qu'ils s'accordent à eux-mêmes. Or ce refus a un prix : il oblige à ne pas se reconnaître soi-même dans le tableau objectif du monde, à se traiter, vu du dehors, autrement qu'on se traite vu du dedans. L'altruisme n'est donc pas un supplément d'âme greffé sur la rationalité : il en est une conséquence, dès lors qu'on admet, comme la pensée objective nous y oblige, que l'on n'est qu'une personne parmi d'autres également réelles. Cette idée, héritée de la leçon de Rawls sur la séparation des personnes, irriguera toute la philosophie politique de Nagel. == Les questions mortelles == Avant de revenir à la politique, il faut faire une place aux essais qui ont donné son titre au recueil ''Questions mortelles'' et qui ont touché un large public. Nagel y aborde des thèmes que la philosophie analytique fréquentait peu : la [[Dictionnaire de philosophie/Mort|mort]], l'[[Dictionnaire de philosophie/Absurde|absurde]], la chance, le sens de la vie. Il le fait avec les mêmes outils que pour la conscience ou la morale, et l'on y retrouve le même conflit des points de vue. === La mort et la privation === L'essai « Death » (1970) pose une question que la tradition épicurienne croyait avoir réglée : la mort est-elle un mal pour celui qui meurt ? Épicure répondait que non : tant que je suis là, la mort n'est pas là ; quand elle est là, je n'y suis plus ; elle ne me concerne donc jamais. Nagel n'est pas convaincu. Si la mort est un mal, accorde-t-il, ce ne peut être en raison d'un état négatif qu'on éprouverait une fois mort, car il n'y a plus alors de sujet pour rien éprouver<ref>Thomas Nagel, « La mort » (« Death »), dans ''MQ'', éd. citée, p.&nbsp;1-10 (« Death » avait d'abord paru dans ''Noûs'', vol.&nbsp;4, 1970, p.&nbsp;73-80).</ref>. Mais il existe des maux qui ne consistent en aucun état ressenti : ce sont les maux de privation. Être trahi à son insu, déchoir sans le savoir, perdre des biens qu'on ignore avoir perdus, voilà des malheurs réels, même si nul désagrément ne les accompagne. La mort, soutient Nagel, est de cet ordre. Elle n'est pas mauvaise par ce qu'elle apporte, mais par ce qu'elle ôte : la vie et les biens qu'elle aurait pu contenir. Le mal de la mort est relatif à ce que la vie interrompue aurait pu être. Cette analyse se heurte à une objection ancienne, formulée par Lucrèce : si l'inexistence après la mort est un mal, pourquoi l'inexistence avant la naissance n'en serait-elle pas un ? Nous ne déplorons pas les siècles qui ont précédé notre venue ; pourquoi déplorer ceux qui suivront notre départ ? Nagel cherche la dissymétrie dans le fait que le temps d'après la mort nous prive d'une vie que nous aurions pu vivre, tandis que le temps d'avant la naissance ne nous prive de rien, puisqu'un homme né plus tôt ne serait plus tout à fait le même homme. La réponse reste discutée, et les commentateurs français s'y sont arrêtés ; elle a le mérite de prendre la peur de la mort au sérieux au lieu de la congédier d'un argument. === L'absurde : une collision avec soi-même === « The Absurd » (1971) s'attaque à un sentiment que beaucoup éprouvent un jour : celui que nos vies sont absurdes. Les raisons qu'on en donne d'ordinaire, dit Nagel, ne tiennent pas. On invoque notre petitesse dans l'immensité du cosmos, la brièveté de nos vies à l'échelle géologique ; mais qu'importerait notre taille ? Si nous étions immenses et éternels, nos vies n'en seraient pas moins absurdes, car ce qui les rend telles ne dépend pas de nos dimensions<ref>Thomas Nagel, « L'absurde » (« The Absurd »), dans ''MQ'', éd. citée, p.&nbsp;11-23 (paru d'abord dans ''The Journal of Philosophy'', vol.&nbsp;68, n{{o}}&nbsp;20, 21 octobre 1971, p.&nbsp;716-727).</ref>. D'où vient alors ce sentiment ? D'une collision intérieure. D'un côté, nous prenons nos vies au sérieux : nous poursuivons des fins, nous nous donnons du mal, nous tenons à mille choses. De l'autre, nous possédons la capacité de prendre du recul, de considérer nos vies du dehors, et de mettre en doute tout ce que nous prenons au sérieux. Sous ce regard détaché, que Nagel décrit par la formule classique, voir les choses ''sub specie aeternitatis'', du point de vue de l'éternité, le système entier de nos justifications apparaît arbitraire, suspendu à des fins que rien ne fonde en dernier ressort. L'absurde naît du heurt de ces deux attitudes que nous ne pouvons abandonner ni l'une ni l'autre : l'engagement sérieux dans nos vies et le doute qui les surplombe<ref>« L'absurde », dans ''MQ'', éd. citée. La définition de l'absurde comme « collision » entre le sérieux de nos engagements et la possibilité permanente de les mettre en doute, et la précision selon laquelle ce heurt est intérieur à nous et non un conflit entre nos attentes et le monde, figurent aux p.&nbsp;13-14 et p.&nbsp;17 de l'édition anglaise.</ref>. C'est là que Nagel se sépare d'Albert Camus. Pour Camus, l'absurde résulte du divorce entre notre exigence de sens et le silence du monde ; il appelle une révolte, et le Sisyphe du ''Mythe'' affronte son destin avec un mépris héroïque. Pour Nagel, l'absurde n'est pas un conflit entre nous et le monde, mais un conflit au-dedans de nous, et il n'appelle ni révolte ni désespoir. Quelle attitude convient, alors ? Nagel répond par une note d'ironie. Le sentiment de l'absurde, écrit-il, ne mérite pas tant de détresse ni tant de défi ; il est même l'une des choses les plus humaines en nous, puisqu'il suppose la capacité de nous transcender en pensée. Si, ''sub specie aeternitatis'', rien ne semble avoir d'importance, alors cela non plus n'a pas d'importance, et nous pouvons aborder nos vies absurdes avec ironie plutôt qu'avec héroïsme ou désespoir<ref>« L'absurde », dans ''MQ'', éd. citée, p.&nbsp;23 : « we can approach our absurd lives with irony instead of heroism or despair ». Nagel oppose son ironie au défi du Sisyphe de Camus.</ref>. La posture héroïque, suggère-t-il, trahit encore une vanité : se croire grave là où l'on est, à l'échelle du cosmos, sans gravité. === La chance morale === « Moral Luck » (1979) met au jour un paradoxe au cœur de notre vie morale. Une idée kantienne nous est familière : on ne saurait juger quelqu'un pour ce qui ne dépend pas de lui. La bonne volonté, disait Kant, brille comme un joyau quel que soit le résultat de l'action ; seul l'usage de la volonté est imputable, non la fortune qui l'entoure. Nagel observe que nous ne jugeons pourtant pas ainsi<ref>Thomas Nagel, « La chance morale » (« Moral Luck »), dans ''MQ'', éd. citée, p.&nbsp;24-38.</ref>. Deux conducteurs commettent la même imprudence ; l'un a la malchance qu'un enfant traverse, l'autre non. Nous tenons le premier pour coupable d'un homicide, le second pour quitte d'une frayeur, alors que la seule différence tient au hasard. Voilà ce que Nagel nomme la chance morale : le fait que notre jugement moral porte en réalité sur des choses qui ne dépendent pas entièrement de l'agent. Il en distingue plusieurs formes. Il y a la chance dans les résultats de nos actes, comme dans l'exemple du conducteur. Il y a la chance dans les circonstances où nous nous trouvons placés : tel homme paisible eût été un bourreau s'il était né dans l'Allemagne des années 1930, et c'est sa chance, non son mérite, de n'avoir jamais eu à subir cette épreuve. Il y a la chance dans nos antécédents, dans la chaîne des causes qui nous ont faits. Il y a enfin la chance dite constitutive : le tempérament, les penchants, le caractère que nous n'avons pas choisis et pour lesquels on nous loue ou nous blâme pourtant. À mesure qu'on suit ce fil, le domaine de ce qui dépend vraiment de nous se rétrécit, jusqu'à menacer de disparaître. Si l'on ne peut être tenu pour responsable que de ce qui relève de notre volonté pure, et si rien, en dernière analyse, n'en relève entièrement, l'idée même de responsabilité morale vacille. Nagel ne prétend pas dissoudre le paradoxe ; il le porte au jour et montre qu'il loge au centre de notre pratique. C'est un cas exemplaire de sa méthode : la pensée objective, en cherchant à situer l'agent dans l'ordre des causes, érode la notion d'agent que la vie morale présuppose, et les deux points de vue s'opposent sans qu'on puisse les réconcilier. == Aux frontières de l'éthique appliquée == Nagel n'a pas séparé la théorie morale de ses applications. Plusieurs de ses essais portent sur des questions concrètes, et chacun possède sa problématique propre : ce sont des analyses autonomes, qui se tiennent par elles-mêmes, et non de simples illustrations d'une thèse générale. On peut néanmoins y reconnaître, en filigrane, la même tension qui parcourt son œuvre, celle qui oppose les exigences impersonnelles au point de vue de l'agent engagé dans des décisions où des vies sont en jeu. === Guerre et massacre === « War and Massacre » (1972) demande s'il existe des limites à ce qu'on peut faire en temps de guerre, même pour une cause juste et même pour gagner. Deux familles de réponses s'opposent, que Nagel nomme l'utilitarisme et l'absolutisme. L'utilitarisme donne la priorité à ce qui va arriver : une action est jugée par ses conséquences, et tout peut en principe être permis si le bilan final est meilleur. L'absolutisme donne la priorité à ce que l'on fait : certaines actions sont interdites en elles-mêmes, quels qu'en soient les résultats<ref>Thomas Nagel, « La guerre et le massacre » (« War and Massacre »), dans ''MQ'', éd. citée, p.&nbsp;53-74 (paru d'abord dans ''Philosophy & Public Affairs'', vol.&nbsp;1, n{{o}}&nbsp;2, 1972, p.&nbsp;123-144). La distinction entre l'utilitarisme, qui donne primauté à « ce qui va arriver », et l'absolutisme, qui donne primauté à « ce que l'on fait », ouvre l'essai.</ref>. Nagel défend, prudemment, une part d'absolutisme. Il existe selon lui des choses qu'on n'a pas le droit de faire à un être humain, même pour empêcher un plus grand mal : massacrer des innocents, torturer, employer la peste ou le feu contre des populations. Ces interdits ne sont pas des calculs déguisés ; ils tiennent à la nature du rapport qu'on entretient avec celui qu'on traite ainsi. L'idée qui les éclaire est celle d'un traitement hostile qui doit rester ajusté à son objet. Lorsque je m'en prends à quelqu'un, mon hostilité doit s'adresser à ce qu'il est ou à ce qu'il fait : on peut combattre un combattant, parce qu'il est partie au conflit. Mais frapper un innocent pour atteindre un autre but, le viser comme un simple moyen, c'est diriger contre lui une action qui ne le concerne pas, et lui faire subir ce que rien en lui ne justifie. L'absolutisme, précise Nagel, n'ordonne pas d'ignorer les conséquences ; il pose une limite que le calcul des conséquences ne doit pas franchir<ref>« La guerre et le massacre », dans ''MQ'', éd. citée. Nagel souligne que l'absolutisme « n'exige pas d'ignorer les conséquences » mais fonctionne comme une limite imposée au raisonnement utilitariste (p.&nbsp;58 et suivantes de l'édition anglaise).</ref>. Il reconnaît la possibilité de situations extrêmes où les deux exigences se contredisent sans recours, où l'on ne peut ni respecter l'interdit ni accepter le désastre. Ces cas ne sont pas une faiblesse de sa thèse ; ils sont le visage, en politique, de la fragmentation des valeurs qu'il tient pour un trait de la condition morale. === La perversion sexuelle === Un essai d'apparence plus légère, « Sexual Perversion » (1969), témoigne de l'étendue des curiosités de Nagel. Il y cherche ce qui distingue le désir sexuel accompli de ses formes tronquées. Sa réponse fait du désir non une simple pulsion dirigée vers un corps, mais une structure de reconnaissance mutuelle à plusieurs étages : je désire l'autre, je m'aperçois qu'il me désire, je perçois qu'il perçoit mon désir, et cet entrelacement des consciences alimente l'excitation<ref>Thomas Nagel, « La perversion sexuelle » (« Sexual Perversion »), dans ''MQ'', éd. citée, p.&nbsp;39-52 (paru d'abord dans ''The Journal of Philosophy'', vol.&nbsp;66, n{{o}}&nbsp;1, 1969, p.&nbsp;5-17). Nagel y emprunte à Jean-Paul Sartre l'analyse de la reconnaissance réciproque des regards.</ref>. Nagel emprunte ce schéma à l'analyse sartrienne du regard. Les perversions, dans son vocabulaire qui n'a rien de moralisateur, seraient les figures où ce circuit de réciprocité se trouve interrompu ou incomplet, où l'un des partenaires cesse d'être pour l'autre une conscience qui répond. L'essai vaut d'abord par cette analyse du désir, qui se passe de toute référence au reste de l'œuvre ; mais on peut, si l'on veut, y rattacher la préoccupation constante de Nagel pour la rencontre entre des points de vue, ici nouée dans l'intimité de deux corps qui se savent l'un l'autre conscients. === La fragmentation de la valeur === Plusieurs de ces essais convergent vers une thèse que Nagel formule dans « The Fragmentation of Value » : il n'existe pas de mesure unique des valeurs, pas de monnaie commune qui permettrait, en cas de conflit, de tout convertir et de calculer la bonne décision<ref>Thomas Nagel, « La fragmentation de la valeur » (« The Fragmentation of Value »), dans ''MQ'', éd. citée, p.&nbsp;128-141.</ref>. Les obligations envers nos proches, les droits des personnes, le bien général, nos engagements particuliers, l'excellence des œuvres : autant de sources de valeur qui parlent des langues différentes et qui peuvent se heurter sans qu'aucune règle supérieure tranche. Cette pluralité n'est pas un défaut de notre savoir moral, qu'une théorie achevée viendrait combler ; elle reflète la diversité des points de vue d'où le monde peut être considéré. L'éthique de Nagel renonce ainsi à l'unité que cherchent l'utilitarisme et le kantisme, au nom de la même fidélité au réel qui lui faisait refuser, en philosophie de l'esprit, la réduction du subjectif à l'objectif. == La philosophie politique == La même tension organise la pensée politique de Nagel. Les institutions justes sont celles qui rendent justice à la fois à la vue impersonnelle, d'où nul ne compte plus qu'un autre, et à la vue personnelle, d'où chacun se soucie d'abord de sa propre vie et de ses proches. Toute la difficulté est de tenir ensemble ces deux exigences sans sacrifier l'une à l'autre. === Égalité et partialité : deux exigences === ''Égalité et partialité'' (1991) part d'un constat que Nagel tire de sa philosophie morale. Chacun de nous est habité par deux points de vue. Du point de vue impersonnel, je me vois comme une personne parmi d'autres, dont la vie n'a pas plus de poids que celle de n'importe qui ; ce point de vue engendre une exigence d'impartialité, et donc une préoccupation égalitaire pour le sort de tous. Du point de vue personnel, je suis cette personne-ci, attachée à ses projets et à ceux qu'elle aime, et porteuse de motifs que l'impartialité ne saurait remplacer. Une société légitime serait celle dont chacun pourrait accepter les principes du double point de vue qu'il occupe, sans avoir à faire taire ni l'exigence impartiale d'égalité ni les attachements partiaux qui donnent à sa vie son prix<ref>Thomas Nagel, ''Égalité et partialité'', trad. Claire Beauvillard, Paris, Presses universitaires de France, 1994, chap. I à III. L'ouvrage traduit ''Equality and Partiality'', New York, Oxford University Press, 1991.</ref>. C'est dire que Nagel cherche, à la suite de Rawls et de Kant, un principe d'unanimité possible : un ordre que nul ne pourrait raisonnablement rejeter. Le problème, reconnaît Nagel, est qu'aucune solution pleinement satisfaisante n'est aujourd'hui en vue. L'exigence impersonnelle pousse vers une égalité que les motivations personnelles ne soutiendront jamais spontanément ; les motivations personnelles, livrées à elles-mêmes, produisent des inégalités que la vue impersonnelle condamne. Entre les deux, la théorie politique ne dispose d'aucune formule qui les réconcilierait sans reste. Nagel ne s'en console pas par un compromis facile : il tient que l'utopie, au sens d'un accord sans tension entre ce qui est juste et ce qui peut effectivement motiver les agents, demeure hors de portée, et que la tâche est de réduire l'écart plutôt que de prétendre l'abolir. Sa philosophie politique a la même honnêteté que sa philosophie morale : elle nomme un conflit qu'elle ne sait pas dissoudre. === Le mythe de la propriété === Avec ''Le mythe de la propriété'' (2002), écrit avec le juriste Liam Murphy, Nagel aborde une question brûlante : l'impôt et la justice fiscale. L'ouvrage tient par sa propre argumentation, juridique et économique autant que philosophique, et l'on aurait tort de le réduire à un corollaire de sa métaphysique des points de vue ; il s'y reconnaît pourtant la même façon de faire prévaloir l'examen impersonnel des institutions sur les intuitions de premier mouvement. La thèse centrale heurte une intuition répandue. On pense d'ordinaire que chacun a d'abord un revenu, fruit de son travail, et que l'État vient ensuite y prélever sa part ; l'impôt apparaît alors comme une atteinte à une propriété antérieure, qu'il faudrait justifier. Murphy et Nagel renversent l'ordre. Il n'existe pas de revenu avant impôt qui aurait une signification morale propre, car la propriété elle-même est l'œuvre d'un système de lois, sans lequel nul ne posséderait rien de stable<ref>Liam Murphy et Thomas Nagel, ''The Myth of Ownership: Taxes and Justice'', New York, Oxford University Press, 2002, chap. 1 et 2. Les auteurs y soutiennent qu'il n'existe pas de droit de propriété antérieur au système juridique et fiscal, et que le revenu avant impôt n'a aucune signification morale indépendante.</ref>. Le marché qui distribue les revenus n'existe que porté par un cadre légal dont l'impôt fait partie intégrante. Parler de ce que l'impôt « prend » à chacun, comme s'il existait une dotation naturelle préalable, relève de ce que les auteurs nomment le libertarisme ordinaire : l'illusion qui traite des droits conventionnels comme s'ils étaient naturels. La conséquence est nette. On ne peut juger un système fiscal en demandant s'il respecte des droits de propriété qui lui préexisteraient, puisque ces droits sont eux-mêmes produits par lui. La seule question pertinente est celle de la justice du système entier de règles, propriété et fiscalité comprises, évalué d'après ses effets sur la vie réelle des personnes. Ce déplacement, où la justice ne porte plus sur le partage d'un gâteau déjà tranché mais sur les institutions qui le découpent, prolonge en théorie fiscale le primat nagélien du point de vue impersonnel. À cette critique du revenu avant impôt, Murphy et Nagel joignent une distinction qu'ils jugent trop souvent négligée, et qui sépare deux fonctions de l'impôt qu'on a tort de confondre. L'impôt sert d'abord à fixer le partage entre ce qui demeure sous le contrôle des particuliers et ce que la collectivité décide de dépenser en commun : c'est sa fonction de fourniture publique, qui finance l'école, la défense, la santé, la recherche ou la culture, ces biens que le marché livré à lui-même n'assure pas. Il sert ensuite à régler la répartition du produit social entre les personnes : c'est la redistribution proprement dite. Or ces deux fonctions, soulignent les auteurs, sont conceptuellement et normativement séparables. On peut tenir à une forte redistribution tout en bornant la dépense publique, ou souhaiter de larges services publics sans viser d'égalisation des revenus ; aucun lien nécessaire ne relie une position sur l'une à une position sur l'autre. La rhétorique politique, qui assimile l'État étendu à l'égalitarisme, brouille un partage qu'il faut tenir net pour juger sainement de l'impôt<ref>Liam Murphy et Thomas Nagel, « Taxes, Redistribution, and Public Provision », ''Philosophy & Public Affairs'', vol.&nbsp;30, n{{o}}&nbsp;1, 2001, p.&nbsp;53-71, thèse reprise dans ''The Myth of Ownership'', éd. citée. Les auteurs y distinguent la fonction de partage entre dépense publique et propriété privée et la fonction de redistribution entre individus, et soutiennent qu'aucun lien nécessaire ne relie les positions prises sur l'une et sur l'autre (p.&nbsp;54-55).</ref>. === La justice par-delà les frontières === L'essai « The Problem of Global Justice » (2005) porte la question de l'égalité au-delà de l'État-nation. Existe-t-il une justice à l'échelle du monde, ou la justice n'a-t-elle de sens qu'entre concitoyens ? Nagel y défend une position qu'on a dite politique, ou associationniste, et qui doit beaucoup à Hobbes. Pour Hobbes, on peut bien découvrir les principes vrais de la justice, mais ils n'ont de force contraignante qu'à l'intérieur d'un État souverain : la justice, comme propriété des relations entre les personnes, requiert un pouvoir capable de garantir à chacun que les autres se plieront aux mêmes règles<ref>Thomas Nagel, « The Problem of Global Justice », ''Philosophy & Public Affairs'', vol.&nbsp;33, n{{o}}&nbsp;2, 2005, p.&nbsp;113-147. Nagel y reprend de Hobbes l'idée que la justice, au sens fort, suppose une souveraineté garantissant l'application des règles, et il en tire que les obligations d'égalité ne s'étendent pas d'emblée à l'échelle mondiale, faute d'institutions souveraines comparables à celles de l'État.</ref>. Nagel juge cette dépendance difficile à récuser. Il en tire que les exigences d'égalité socio-économique, celles qui valent entre les membres d'un même État, ne s'étendent pas telles quelles à l'humanité entière, faute d'institutions mondiales comparables. Ce que nous devons aux étrangers lointains relève alors de l'humanité et des droits fondamentaux, non de la justice distributive au sens plein. Cette thèse a paru austère, et elle a nourri une discussion nourrie en théorie politique, où les tenants d'une justice cosmopolite ont objecté que l'interdépendance économique mondiale crée déjà les rapports denses que Nagel réserve à l'État. Lui-même n'en fait pas une fatalité : il esquisse un chemin hobbesien où la justice mondiale, aujourd'hui hors d'atteinte, pourrait naître un jour de la croissance d'institutions internationales d'abord imparfaites, voire imposées, avant de devenir légitimes. La justice globale serait moins un point de départ qu'un terme lointain, suspendu à l'apparition d'un pouvoir qui n'existe pas encore. == La raison a le dernier mot == Avec ''The Last Word'' (1997), Nagel revient au cœur de son rationalisme et livre sa défense la plus frontale de la raison contre les philosophies qui prétendent la réduire à un point de vue parmi d'autres. La cible est le subjectivisme ou le relativisme à propos de la raison elle-même : l'idée que nos pensées les plus élémentaires, en logique, en mathématiques, en éthique, ne seraient que l'expression de notre constitution, de notre culture ou de notre langage, sans portée qui les dépasse. À cette idée Nagel oppose un argument de réfutation par soi-même. Celui qui veut relativiser la raison doit encore raisonner pour le faire : il avance des prémisses, en tire des conséquences, prétend que sa position est vraie et que la position adverse est fausse. Or ces gestes mêmes engagent les normes de la raison qu'il voulait congédier. On ne peut critiquer ses propres prétentions de la raison, écrit Nagel, sans employer la raison, à un moment ou à un autre, pour formuler et soutenir cette critique<ref>Thomas Nagel, ''The Last Word'', New York, Oxford University Press, 1997, p.&nbsp;15 : « we cannot criticize some of our own claims of reason without employing reason at some point to formulate and support those criticisms ». Nagel y soutient que toute tentative de relativiser la raison se réfute elle-même, puisqu'elle doit recourir à la raison pour s'énoncer. L'ouvrage n'a pas été traduit en français.</ref>. La pensée rationnelle a donc le dernier mot : on ne peut passer derrière elle pour la juger du dehors, car tout jugement la suppose déjà. Reprenant une image qui lui est chère, Nagel dit que nos pensées de premier ordre se soumettent à l'ordre des raisons au lieu de le créer : elles répondent à quelque chose qu'elles ne fabriquent pas. Cette conviction le rapproche de positions qu'il avait rencontrées chez d'autres. Il rappelle ce qu'il doit à un séminaire de Saul Kripke sur le caractère non conventionnel de la logique, et il rapproche sa démarche de celle de Ronald Dworkin en théorie morale, pour qui une objection sceptique de second ordre contre la morale n'est jamais qu'une prise de position morale de plus, qui se discute sur le même terrain que les jugements qu'elle conteste. Dans les deux cas, il s'agit de montrer qu'on ne sort pas du jeu de la raison ou de la morale en prétendant le survoler, parce que la sortie supposée n'est qu'un coup joué à l'intérieur. ''The Last Word'' est ainsi le versant épistémologique du programme que ''Le point de vue de nulle part'' menait en métaphysique : l'objectivité de la raison y est défendue contre la tentation de la dissoudre dans le contingent. == L'esprit et le cosmos == ''L'esprit et le cosmos'' (2012) est le dernier grand ouvrage théorique autonome de Nagel, et celui de tous qui a suscité la plus large controverse, pour des raisons qui débordent la philosophie. Il a publié depuis ''Analytic Philosophy and Human Life'' (2023), mais ce volume rassemble des essais et des comptes rendus plutôt qu'il ne développe une thèse continue, de sorte que ''L'esprit et le cosmos'' demeure son dernier livre systématique. Il y porte à ses ultimes conséquences l'intuition de toute son œuvre : si la conscience résiste à la réduction physicaliste, alors le problème qu'elle pose n'est pas un détail local de la théorie de l'esprit, mais une fissure qui traverse notre image entière de la nature. Le sous-titre l'annonce sans détour : la conception matérialiste et néo-darwinienne de la nature est, selon toute vraisemblance, fausse. === Une lacune au cœur de l'image scientifique === Le raisonnement reprend la pointe de « Quel effet cela fait-il d'être une chauve-souris ? » et l'étend à la cosmologie. Les sciences de la nature, depuis Galilée et Descartes, ont obtenu leur puissance au prix d'une mise à l'écart de l'esprit : elles décrivent un monde de quantités physiques d'où la conscience a été retranchée pour devenir l'objet à expliquer. Mais ce monde, à un moment de son histoire, a produit des êtres conscients, doués de sensations, de pensées, de valeurs. Or si la conscience ne se laisse pas dériver des seules propriétés physiques, sa venue reste inexplicable dans le cadre que les sciences se sont donné. Une cosmologie complète, soutient Nagel, devrait rendre intelligible le fait que l'univers ait engendré des esprits ; le matérialisme contemporain en est incapable, parce qu'il a d'avance exclu de la nature ce qu'il faudrait pour le comprendre<ref>Thomas Nagel, ''L'esprit et le cosmos. Pourquoi la conception matérialiste et néo-darwinienne de la nature est presque certainement fausse'', trad. Dominique Berlioz et François Loth, Paris, Vrin, 2018, chap. 1. L'ouvrage traduit ''Mind and Cosmos. Why the Materialist Neo-Darwinian Conception of Nature Is Almost Certainly False'', New York, Oxford University Press, 2012.</ref>. Trois choses échappent ainsi au filet matérialiste : la conscience, la connaissance objective et la valeur. La cognition pose un problème voisin de celui de la conscience : que des êtres issus de l'évolution soient capables d'atteindre des vérités objectives, en mathématiques ou en morale, qui n'ont aucun rapport avec leur survie, voilà qui demande une explication que la sélection naturelle ne fournit pas. === Une téléologie sans Dieu === À ce diagnostic, Nagel ajoute une proposition qui a déconcerté. Pour rendre compte de l'apparition de l'esprit, il faudrait peut-être admettre dans la nature des principes d'un autre type que les lois mécaniques : des principes téléologiques, orientés, en vertu desquels l'univers tendrait, par sa constitution même, à produire de la conscience et de la valeur. Non pas un dessein imposé du dehors, mais une tendance interne inscrite dans l'ordre des choses. Nagel prend soin de distinguer cette hypothèse de toute théologie. Athée revendiqué, il dit ne pas éprouver le besoin d'un Dieu et ne pas posséder ce sens du divin qui rend la religion vivante pour d'autres ; il cherche une explication immanente, et la téléologie naturelle qu'il appelle de ses vœux n'a pas plus besoin d'un créateur que les lois physiques<ref>''L'esprit et le cosmos'', éd. citée, chap. 4. Nagel y avance que des principes téléologiques naturels, distincts d'une intervention divine, pourraient être requis pour expliquer l'orientation de la nature vers la conscience et la valeur ; il rappelle son athéisme et son absence de toute sensibilité religieuse.</ref>. On reconnaît là sa fidélité à un monde objectif qui ne se réduit pourtant pas au seul physique : si la réalité enveloppe l'esprit, alors l'image scientifique doit s'élargir, fût-ce vers des principes que la science d'aujourd'hui ignore. C'est moins le rejet de la science que l'exigence d'une science assez ample pour faire place à ce qu'elle avait commencé par exclure. === Une controverse retentissante === Le livre a provoqué de vives réactions. En accordant aux critiques empiriques que les partisans du dessein intelligent adressent au darwinisme une attention qu'on jugeait compromettante, Nagel s'est trouvé pris dans une querelle qui dépassait la philosophie. Beaucoup de scientifiques et de philosophes ont vu dans ''L'esprit et le cosmos'' une concession dangereuse faite aux adversaires de l'évolution, et l'ouvrage a été attaqué avec une vivacité peu commune, plusieurs commentateurs le jugeant très sévèrement<ref>Sur l'ampleur de la polémique anglo-saxonne, voir Andrew Ferguson, « The Heretic », ''The Weekly Standard'', 25 mars 2013, qui en dresse la chronique : le psychologue Steven Pinker y reproche publiquement à Nagel un raisonnement défaillant, et le livre est éreinté lors du colloque « Moving Naturalism Forward » réuni autour de Daniel Dennett et Richard Dawkins.</ref>. La discussion française n'a pas été en reste : la critique a relevé la faiblesse des arguments biologiques et la difficulté du recours à la téléologie, tout en saluant parfois la franchise d'un penseur qui osait formuler tout haut un malaise devant le réductionnisme régnant<ref>Sur la réception française, voir Roger Pouivet, « Après le matérialisme ? », ''La Vie des idées'', 14 mars 2019, ainsi que le dossier « Thomas Nagel » dirigé par François Loth dans la revue ''Klesis'' (n{{o}}&nbsp;41, 2018). Les commentateurs y discutent la solidité des objections biologiques de Nagel et la portée de son hypothèse téléologique, plusieurs jugeant l'argument fragile tout en reconnaissant la cohérence de son refus du réductionnisme.</ref>. Nagel n'a pas cherché à se rétracter. Il a maintenu qu'il ne défendait aucune doctrine religieuse, mais réclamait seulement le droit de tenir pour ouvert un problème que les approches matérialistes dominantes déclaraient clos. L'épisode illustre une constante de sa carrière : la disposition à suivre un argument jusqu'où il mène, même au prix de l'isolement, et à préférer une question franchement posée à un consensus rassurant. == Réception et postérité == L'œuvre de Nagel occupe une place à part dans la philosophie analytique des dernières décennies. Elle en partage les outils, la clarté, le goût de l'argument exact, mais elle les met au service de questions que cette tradition avait souvent laissées de côté, et elle conteste de l'intérieur l'un de ses présupposés les plus répandus, le matérialisme. De là une réception partagée entre l'admiration pour la pénétration des analyses et la résistance devant des conclusions jugées trop concessives au mystère. === Les discussions philosophiques === ''Le point de vue de nulle part'' a aussitôt été reconnu comme un livre majeur, mais sa thèse a été éprouvée. Dans un compte rendu critique au titre éloquent, « No Resting Place », Christopher Peacocke a montré que le balancement entre le subjectif et l'objectif, tel que Nagel le décrit, ne laisse au lecteur aucun point de repos : si l'objectivité est affaire de degré, et si la vue objective ne peut jamais englober tout le réel puisque « la réalité n'est pas seulement la réalité objective », alors la pensée semble condamnée à osciller sans fin entre deux pôles dont aucun n'est pleinement habitable, et le problème central pourrait bien rester insoluble<ref>Christopher Peacocke, « No Resting Place: A Critical Notice of ''The View from Nowhere'' », ''The Philosophical Review'', vol.&nbsp;98, n{{o}}&nbsp;1, 1989, p.&nbsp;65-82. Peacocke y relève que la conception de l'objectivité comme affaire de degré et la thèse selon laquelle « la réalité n'est pas seulement la réalité objective » (''VFN'', p.&nbsp;87) laissent la pensée osciller entre subjectif et objectif sans point de stabilisation, le problème central paraissant à Nagel lui-même peut-être insoluble.</ref>. L'objection ne réfute pas Nagel ; elle nomme le malaise que son livre assume, celui d'une dualité de perspectives qu'aucune synthèse ne vient clore. ''The Last Word'' a connu un sort comparable. Simon Blackburn, dans un compte rendu nuancé, salue en Nagel un champion résolu de la raison et juge admirable son refus du relativisme, mais trouve l'argumentation déroutante. Le point de litige est subtil. Que nos affirmations de premier ordre l'emportent sur les contestations relativistes, qu'à dire « il fait froid » je l'emporte sur qui répliquerait « ce n'est que votre point de vue », Blackburn l'accorde volontiers ; mais cette domination, observe-t-il, se joue au premier ordre, et ne tranche pas la question de second ordre que le relativiste, lui, croit poser sur la nature de nos pensées<ref>Simon Blackburn, compte rendu de ''The Last Word'', ''The Philosophical Review'', vol.&nbsp;107, n{{o}}&nbsp;4, 1998, p.&nbsp;653-656. Blackburn y reconnaît la valeur de l'anti-relativisme de Nagel mais lui reproche d'osciller entre une réponse de premier ordre, qui rappelle que les spéculations sceptiques sont subordonnées aux certitudes ordinaires, et une réponse de second ordre, qui prétendrait à une harmonie de la pensée avec un ordre objectif du monde, sans établir que la première suffise à gagner la seconde.</ref>. Nagel, selon Blackburn, hésite entre deux réponses au relativiste, l'une minimale et de premier ordre, l'autre ambitieuse et métaphysique, et la première ne suffit pas à emporter la seconde. La critique vise moins la conviction de Nagel que la façon dont l'argument prétend l'établir. === Une influence durable === Par-delà ces controverses, l'influence de Nagel s'est exercée en profondeur sur la philosophie de l'esprit. Sa question sur la chauve-souris est devenue l'un des points de départ obligés de tout débat sur la conscience, et c'est en la prolongeant que David Chalmers a formulé, dans les années 1990, sa distinction entre les problèmes « faciles » et le problème « difficile » de la conscience, celui de l'expérience vécue. Le legs de Nagel se reconnaît encore dans la fortune des arguments anti-physicalistes, dans la vitalité de la réflexion sur les qualités subjectives de l'expérience, et dans la légitimité reconquise de questions, sur la mort, l'absurde, le sens de la vie, que la philosophie analytique tient désormais pour siennes. Tenu pour l'un des philosophes vivants les plus considérés des États-Unis, distingué par le prix Rolf Schock et le prix Balzan, Nagel laisse une œuvre dont l'unité tient moins à un système qu'à une fidélité : celle d'un esprit qui n'a cessé de revenir au point où le monde vu du dedans rencontre le monde vu du dehors, et qui a tenu pour une tâche de la philosophie de ne sacrifier ni l'un ni l'autre. == Conclusion == L'œuvre de Thomas Nagel se laisse lire comme la variation patiente d'un seul thème. De la conscience à la mort, de l'altruisme à l'impôt, de la raison à la cosmologie, c'est toujours le rapport entre le point de vue subjectif et le point de vue objectif qui se rejoue, et toujours le refus de résoudre la tension en supprimant l'un de ses termes. Le physicalisme voudrait absorber le subjectif dans l'objectif : Nagel objecte qu'il reste alors un effet que cela fait d'être tel sujet, irréductible à toute description du dehors. L'égoïsme voudrait s'en tenir au subjectif : Nagel objecte que la pensée objective nous force à nous reconnaître comme une personne parmi d'autres également réelles. Le relativisme voudrait dissoudre la raison dans le contingent : Nagel objecte qu'on ne peut la contester sans déjà s'en servir. Partout la même structure, et partout la même honnêteté à nommer les conflits que sa philosophie ne sait pas dissoudre, la fragmentation des valeurs, l'écart entre ce qui est juste et ce qui peut motiver les agents, le balancement sans repos du subjectif et de l'objectif. Cette honnêteté devant la difficulté est un trait constant de sa démarche. Contre la tentation, fréquente en philosophie, de gagner en simplicité ce qu'on perd en vérité, Nagel a préféré une image du monde et de nous-mêmes plus complexe, mais plus fidèle à l'expérience que nous en avons. Il a tenu que certaines questions méritent d'être maintenues ouvertes, que certains problèmes valent mieux qu'une solution prématurée, et qu'à ses yeux la tâche du philosophe est d'abord de ne pas se mentir sur la difficulté de ce qu'il cherche. C'est ce qui donne à une œuvre aussi diverse sa cohérence, et ce qui explique qu'elle reste lue et discutée, par-delà les désaccords qu'elle suscite, pour la façon dont elle s'efforce de penser ensemble le sujet et le monde. == Notes et références == {{Références|colonnes=2}} == Bibliographie == === Œuvres traduites en français === * Thomas Nagel, ''Questions mortelles'', trad. Pascal Engel et Claudine Tiercelin, Paris, Presses universitaires de France, coll. « Philosophie d'aujourd'hui », 1983 (éd. originale : ''Mortal Questions'', Cambridge, Cambridge University Press, 1979). * Thomas Nagel, ''Le point de vue de nulle part'', trad. Sonia Kronlund, Combas, Éditions de l'éclat, 1993 (éd. originale : ''The View from Nowhere'', New York, Oxford University Press, 1986). * Thomas Nagel, ''Qu'est-ce que tout cela veut dire ? Une très brève introduction à la philosophie'', trad. Ruwen Ogien, Combas, Éditions de l'éclat, 1993 (éd. originale : ''What Does It All Mean? A Very Short Introduction to Philosophy'', New York, Oxford University Press, 1987). * Thomas Nagel, ''Égalité et partialité'', trad. Claire Beauvillard, Paris, Presses universitaires de France, coll. « Philosophie morale », 1994 (éd. originale : ''Equality and Partiality'', New York, Oxford University Press, 1991). * Thomas Nagel, ''L'esprit et le cosmos. Pourquoi la conception matérialiste et néo-darwinienne de la nature est presque certainement fausse'', trad. Dominique Berlioz et François Loth, Paris, Vrin, coll. « Analyse et philosophie », 2018 (éd. originale : ''Mind and Cosmos'', New York, Oxford University Press, 2012). === Principales œuvres non traduites === * Thomas Nagel, ''The Possibility of Altruism'', Oxford, Clarendon Press, 1970 (réimpr. Princeton, Princeton University Press, 1978). * Thomas Nagel, ''The Last Word'', New York, Oxford University Press, 1997. * Liam Murphy et Thomas Nagel, ''The Myth of Ownership: Taxes and Justice'', New York, Oxford University Press, 2002. * Thomas Nagel, ''Concealment and Exposure and Other Essays'', New York, Oxford University Press, 2002. * Thomas Nagel, « The Problem of Global Justice », ''Philosophy & Public Affairs'', vol.&nbsp;33, n{{o}}&nbsp;2, 2005, p.&nbsp;113-147. * Thomas Nagel, ''Analytic Philosophy and Human Life'', New York, Oxford University Press, 2023. * Thomas Nagel, ''What Is It Like to Be a Bat?'', New York, Oxford University Press, 2024 (réédition de l'essai de 1974 accompagnée d'une préface de l'auteur). === Études === * Roger Pouivet, « Après le matérialisme ? », recension de ''L'esprit et le cosmos'', ''La Vie des idées'', 14 mars 2019. * ''Klesis. Revue philosophique'', n{{o}}&nbsp;41, 2018, dossier « Thomas Nagel » (dir. François Loth). * Simon Blackburn, compte rendu de ''The Last Word'', ''The Philosophical Review'', vol.&nbsp;107, n{{o}}&nbsp;4, 1998, p.&nbsp;653-656. * Christopher Peacocke, « No Resting Place: A Critical Notice of ''The View from Nowhere'' », ''The Philosophical Review'', vol.&nbsp;98, n{{o}}&nbsp;1, 1989, p.&nbsp;65-82. * Alan Thomas, ''Thomas Nagel'', Durham, Acumen, coll. « Philosophy Now », 2009. == Voir aussi == * [[Dictionnaire de philosophie/Conscience|Conscience]] * [[Dictionnaire de philosophie/Dualisme|Dualisme]] * [[Dictionnaire de philosophie/Émergence|Émergence]] * [[Dictionnaire de philosophie/Intelligence animale|Intelligence animale]] * [[Dictionnaire de philosophie/Expérience de pensée|Expérience de pensée]] * [[Dictionnaire de philosophie/David Chalmers|David Chalmers]] * [[Dictionnaire de philosophie/Altruisme|Altruisme]] * [[Dictionnaire de philosophie/Morale|Morale]] * [[Dictionnaire de philosophie/Mort|Mort]] * [[Dictionnaire de philosophie/Absurde|Absurde]] * [[Dictionnaire de philosophie/Égalité|Égalité]] * [[Dictionnaire de philosophie/Absolutisme|Absolutisme]] * [[Dictionnaire de philosophie/Scepticisme|Scepticisme]] * [[Dictionnaire de philosophie/Métaphysique|Métaphysique]] [[Catégorie:Dictionnaire de philosophie (livre)]] [[Catégorie:Philosophe]] {{DEFAULTSORT:Nagel, Thomas}} lokzau727agdtvplwlb7niwfyk8aoyt Mathc matrices/09b 0 83964 768474 2026-06-24T08:30:39Z Xhungab 23827 news 768474 wikitext text/x-wiki __NOTOC__ [[Catégorie:Mathc matrices (livre)]] [[Mathc_matrices/Sommaire| Sommaire]] {{Partie{{{type|}}}| '''Système dynamique linéaire discret .'''}} Soit : u_n+1 = a11 u_n + a12 v_n v_n+1 = a21 u_n + a22 v_n Que l'on peu écrire : (t : transposé) X_n = [u_n, v_n]t et alors X_n+1 = A X_n X_n+1 = [u_n+1,v_n+1]t Posons X_0 = [u_0,v_0]t Alors X_1 = A X_0 X_2 = A X_1 = A^2 X_0 X_3 = A X_2 = A^3 X_0 ... X_n = A^n X_0 Calculez : lim X_n = n-> oo Pour cela nous allons utiliser les valeurs propres et les vecteurs propres pour la première méthode, et pour la seconde méthode nous calculerons directement la puissance de A. Exemple 1 : * [[Mathc matrices/097| c00a.c ]] : Calculons les vecteurs propres et les valeurs propres. * [[Mathc matrices/098| c00b.c ]] : Calculons A^P Nous pourrons observer qu'a partir de P = 19, la valeur de A^P n'évolue plus. Exemple 2 : * [[Mathc matrices/099| c00c.c ]] : Calculons les vecteurs propres et les valeurs propres. * [[Mathc matrices/09a| c00d.c ]] Calculons A^n Nous pourrons observer qu'a partir de P = 17, la valeur de A^P n'évolue plus. {{AutoCat}} 16k5bx1pqf5ktpygwn0hblsb636akd9 Mathc matrices/097 0 83965 768475 2026-06-24T08:34:55Z Xhungab 23827 news 768475 wikitext text/x-wiki [[Catégorie:Mathc matrices (livre)]] [[Mathc matrices/09b| '''Application''']] Installer et compiler ces fichiers dans votre répertoire de travail. {{Fichier|c00a.c|largeur=70%|info=|icon=Crystal128-source-c.svg}} <syntaxhighlight lang="c"> /* ------------------------------------ */ /* Save as: c00a.c */ /* ------------------------------------ */ #include "v_a.h" /* ------------------------------------ */ #define RCA C2 /* ------------------------------------ */ int main(void) { double a[RCA*RCA]={ +0,+1, -1./2.,+3./2. }; double **A = ca_A_mR(a, i_mR(RCA,RCA)); double **Ev = eigs_V_mR(A, i_mR(RCA,RCA)); double **InvEv = invgj_mR(Ev, i_mR(RCA,RCA)); /* Eval = InvEv A Ev */ double **T1 = mul_mR(InvEv, A, i_mR(RCA,RCA)); double **Eval = mul_mR(T1, Ev, i_mR(RCA,RCA)); clrscrn(); printf(" Copy/Paste into the octave windows \n"); p_Octave_mR(A,"a",P9); printf(" [V, E] = eigs (a,%d) \n\n",RCA); printf(" Ev:"); p_mR(Ev,S10,P4,C6); printf(" Eval = InvEv A Ev"); p_mR(Eval,S10,P4,C6); stop(); f_mR(A); f_mR(Ev); f_mR(InvEv); f_mR(Eval); f_mR(T1); return 0; } /* ------------------------------------ */ /* ------------------------------------ */ </syntaxhighlight> '''Exemple de sortie écran :''' <syntaxhighlight lang="c"> Copy/Paste into the octave windows a=[ +0.000000000,+1.000000000; -0.500000000,+1.500000000] [V, E] = eigs (a,2) Ev: +0.7071 +0.8944 +0.7071 +0.4472 Eval = InvEv A Ev +1.0000 -0.0000 +0.0000 +0.5000 Press return to continue. </syntaxhighlight> {{AutoCat}} r1fucpaogahceembdo9loz1o7sztqm4 Mathc matrices/098 0 83966 768476 2026-06-24T08:38:00Z Xhungab 23827 news 768476 wikitext text/x-wiki [[Catégorie:Mathc matrices (livre)]] [[Mathc matrices/09b| '''Application''']] Installer et compiler ces fichiers dans votre répertoire de travail. {{Fichier|c00b.c|largeur=70%|info=|icon=Crystal128-source-c.svg}} <syntaxhighlight lang="c"> /* ------------------------------------ */ /* Save as: c00b.c */ /* ------------------------------------ */ #include "v_a.h" /* ------------------------------------ */ #define RCA C2 #define P 20/* Try : 10, 15, 20, 25 */ /* ------------------------------------ */ /* ------------------------------------ */ double f( double x) { return(pow(x,P)); } char feq[] = "x**P"; /* ------------------------------------ */ /* ------------------------------------ */ int main(void) { double a[RCA*RCA]={ +0,+1, -1./2.,+3./2. }; double **A = ca_A_mR(a, i_mR(RCA,RCA)); double **A_P = pow_mR(P, A, i_mR(RCA,RCA)); double **Ev = eigs_V_mR(A, i_mR(RCA,RCA)); double **InvEv = invgj_mR(Ev, i_mR(RCA,RCA)); /* Eval = InvEv A Ev */ double **T = mul_mR(InvEv, A, i_mR(RCA,RCA)); double **Eval = mul_mR(T, Ev, i_mR(RCA,RCA)); double **f_Eval = i_mR(RCA,RCA); clrscrn(); printf(" Copy/Paste into the octave windows \n"); p_Octave_mR(A,"A",P9); printf(" A^%d\n\n",P); printf(" A^%d:",P); pE_mR(A_P,S10,P4,C6); printf(" A^%d: Ev Eval**%d InvEv",P,P); f_eigs_mR(f,Eval,f_Eval); mul_mR(Ev,f_Eval,T); mul_mR(T,InvEv,A_P); pE_mR(A_P,S10,P4,C6); stop(); f_mR(A); f_mR(A_P); f_mR(Ev); f_mR(InvEv); f_mR(Eval); f_mR(f_Eval); f_mR(T); return 0; } /* ------------------------------------ */ /* ------------------------------------ */ </syntaxhighlight> '''Exemple de sortie écran :''' <syntaxhighlight lang="c"> Copy/Paste into the octave windows A=[ +0.000000000,+1.000000000; -0.500000000,+1.500000000] A^20 A^20: -1.0000e+00 +2.0000e+00 -1.0000e+00 +2.0000e+00 A^20: Ev Eval**20 InvEv -1.0000e+00 +2.0000e+00 -1.0000e+00 +2.0000e+00 Press return to continue. </syntaxhighlight> {{AutoCat}} 9da65rxzl6hykvnqmu23csgg6lad6t1 Mathc matrices/099 0 83967 768477 2026-06-24T08:39:56Z Xhungab 23827 news 768477 wikitext text/x-wiki [[Catégorie:Mathc matrices (livre)]] [[Mathc matrices/09b| '''Application''']] Installer et compiler ces fichiers dans votre répertoire de travail. {{Fichier|c00c.c|largeur=70%|info=|icon=Crystal128-source-c.svg}} <syntaxhighlight lang="c"> /* ------------------------------------ */ /* Save as: c00c.c */ /* ------------------------------------ */ #include "v_a.h" /* ------------------------------------ */ #define RCA C2 /* ------------------------------------ */ int main(void) { double a[RCA*RCA]={ +0.8,+0.3, +0.2,+0.7 }; double **A = ca_A_mR(a, i_mR(RCA,RCA)); double **Ev = eigs_V_mR(A, i_mR(RCA,RCA)); double **InvEv = invgj_mR(Ev, i_mR(RCA,RCA)); /* Eval = InvEv A Ev */ double **T1 = mul_mR(InvEv, A, i_mR(RCA,RCA)); double **Eval = mul_mR(T1, Ev, i_mR(RCA,RCA)); clrscrn(); printf(" Copy/Paste into the octave windows \n"); p_Octave_mR(A,"a",P9); printf(" [V, E] = eigs (a,%d) \n\n",RCA); printf(" Ev:"); p_mR(Ev,S10,P4,C6); printf(" Eval = InvEv A Ev"); p_mR(Eval,S10,P4,C6); stop(); f_mR(A); f_mR(Ev); f_mR(InvEv); f_mR(Eval); f_mR(T1); return 0; } /* ------------------------------------ */ /* ------------------------------------ */ </syntaxhighlight> '''Exemple de sortie écran :''' <syntaxhighlight lang="c"> Copy/Paste into the octave windows a=[ +0.800000000,+0.300000000; +0.200000000,+0.700000000] [V, E] = eigs (a,2) Ev: +0.8321 +0.7071 +0.5547 -0.7071 Eval = InvEv A Ev +1.0000 +0.0000 -0.0000 +0.5000 Press return to continue. </syntaxhighlight> {{AutoCat}} i7eqwhvt5cdpiugf5k1q19not3m4k3z Mathc matrices/09a 0 83968 768478 2026-06-24T08:42:10Z Xhungab 23827 news 768478 wikitext text/x-wiki [[Catégorie:Mathc matrices (livre)]] [[Mathc matrices/09b| '''Application''']] Installer et compiler ces fichiers dans votre répertoire de travail. {{Fichier|c00d.c|largeur=70%|info=|icon=Crystal128-source-c.svg}} <syntaxhighlight lang="c"> /* ------------------------------------ */ /* Save as: c00d.c */ /* ------------------------------------ */ #include "v_a.h" /* ------------------------------------ */ #define RCA C2 #define P 17/* Try : 10, 15, 20, 25 */ /* ------------------------------------ */ /* ------------------------------------ */ double f( double x) { return(pow(x,P)); } char feq[] = "x**P"; /* ------------------------------------ */ /* ------------------------------------ */ int main(void) { double a[RCA*RCA]={ +0.8,+0.3, +0.2,+0.7 }; double **A = ca_A_mR(a, i_mR(RCA,RCA)); double **A_P = pow_mR(P, A, i_mR(RCA,RCA)); double **Ev = eigs_V_mR(A, i_mR(RCA,RCA)); double **InvEv = invgj_mR(Ev, i_mR(RCA,RCA)); /* Eval = InvEv A Ev */ double **T = mul_mR(InvEv, A, i_mR(RCA,RCA)); double **Eval = mul_mR(T, Ev, i_mR(RCA,RCA)); double **f_Eval = i_mR(RCA,RCA); clrscrn(); printf(" Copy/Paste into the octave windows \n"); p_Octave_mR(A,"A",P9); printf(" A^%d\n\n",P); printf(" A^%d:",P); pE_mR(A_P,S10,P4,C6); printf(" A^%d: Ev Eval**%d InvEv",P,P); f_eigs_mR(f,Eval,f_Eval); mul_mR(Ev,f_Eval,T); mul_mR(T,InvEv,A_P); pE_mR(A_P,S10,P4,C6); stop(); f_mR(A); f_mR(A_P); f_mR(Ev); f_mR(InvEv); f_mR(Eval); f_mR(f_Eval); f_mR(T); return 0; } /* ------------------------------------ */ /* ------------------------------------ */ </syntaxhighlight> '''Exemple de sortie écran :''' <syntaxhighlight lang="c"> Copy/Paste into the octave windows A=[ +0.800000000,+0.300000000; +0.200000000,+0.700000000] A^17 A^17: +6.0000e-01 +6.0000e-01 +4.0000e-01 +4.0000e-01 A^17: Ev Eval**17 InvEv +6.0000e-01 +6.0000e-01 +4.0000e-01 +4.0000e-01 Press return to continue. </syntaxhighlight> {{AutoCat}} h34zltcbhmlp2e9o7dro1zw2ddckbj1