source: pyromaths/trunk/fuentes/src/pyromaths/classes/Racine.py @ 423

Last change on this file since 423 was 423, checked in by mabarracus, 4 years ago

add sources from pyromaths 15.10

File size: 12.0 KB
Line 
1# -*- coding: utf-8 -*-
2
3from pyromaths.outils.decimaux import decimaux
4from pyromaths.outils.Arithmetique import carrerise, pgcd, ppcm, factor
5from math import sqrt
6from Fractions import Fraction
7
8def produitfacteurs(facteurs):
9    """Affiche sous forme de produit les éléments d'une liste."""
10    prodfacteurs = ''
11    for element in facteurs:
12        prodfacteurs += str(element) + ' \\times '
13    return prodfacteurs[:-7]
14
15class Racine:
16    def __init__(self, radicande, coeff=1, indice=2):
17        if (radicande < 0) or not (isinstance(indice, int)):
18            print "Erreur de définition ! Le radicande doit être positif et l'indice un nombre entier !"
19        self.radicande = radicande
20        self.indice = indice  # Nombre entier
21        self.coeff = coeff  # Coeff devant la racine
22
23    def __add__(self, other):
24        if not (isinstance(other, Racine)):
25            return str(self) + " + " + str(other)
26        if (self.radicande == other.radicande) and (self.indice == other.indice):
27            return [str(self.simplifie()[0]) + "+" + str(other.simplifie()[0]), Racine(self.radicande, self.coeff + other.coeff, self.indice)]
28        else:
29            return str(self) + " + " + str(other)
30
31    def __radd__(self, other):
32        return self +other
33
34    def __sub__(self, other):
35        if not (isinstance(other, Racine)):
36            return str(self) + " + " + str(other)
37        if (self.radicande == other.radicande) and (self.indice == other.indice):
38            return Racine(self.radicande, self.coeff - other.coeff, self.indice)
39        else:
40            return (str(self) + " - " + str(other), "tset")
41
42    def __rsub__(self, other):
43        return -(self -other)
44
45    def __mul__(self, other):
46        if (isinstance(other, float)) or (isinstance(other, int)):
47            return Racine(self.radicande, self.coeff * other, self.indice)
48        elif self.indice == other.indice:
49            return Racine(self.radicande * other.radicande, self.coeff * other.coeff, self.indice)
50        else:
51            return str(self) + ' x ' + str(other)
52
53    def __rmul__(self, other):
54        return self * other
55
56    def __div__(self, other):
57        if (isinstance(other, float)) or (isinstance(other, int)):
58            return Racine(self.radicande, self.coeff / other, self.indice)
59        elif self.indice == other.indice:
60            return Racine(self.radicande / float(other.radicande), self.coeff / float(other.coeff), self.indice)
61        else:
62            return str(self) + ' / ' + str(other)
63
64    def __rdiv__(self, other):
65        if (isinstance(other, float)) or (isinstance(other, int)):
66            return Racine(self.radicande, other / float(self.coeff * self.radicande), self.indice)
67        elif self.indice == other.indice:
68            return Racine(other.radicande / float(self.radicande), other.coeff / float(self.coeff), self.indice)
69        else:
70            return str(other) + ' / ' + str(self)
71
72    def __str__(self):
73        if self.coeff == 0:
74            return "0"
75        else:
76            if self.coeff == 1:
77                coeff = ""
78            else:
79                coeff = decimaux(self.coeff, 1) + " \\, "
80            if self.radicande == 0:
81                coeff = ""
82                racine = ""
83                radicande = "0"
84            elif self.indice == 2:
85                racine = "\\sqrt{"
86                radicande = decimaux(self.radicande, 1) + "}"
87            else:
88                racine = "\\sqrt[{0}]{{".format(self.indice)
89                radicande = decimaux(self.radicande, 1) + "}"
90            return coeff + racine + radicande
91
92    def simplifie(self):
93        facteurs = factor(self.radicande)
94        prodfacteurs = produitfacteurs(facteurs)
95        if self.indice == 2:
96            racine = "\\sqrt{"
97        else:
98            racine = "\\sqrt[{0}]{{".format(self.indice)
99        coeff = self.coeff
100        radicande = self.radicande
101        detail = [str(self), ' = ', str(coeff) + racine + prodfacteurs + '}']
102        for element in facteurs:
103            if facteurs.count(element) % self.indice == 0:
104                coeff *= element
105                for dummy in range(self.indice):
106                    facteurs.remove(element)
107                radicande = radicande // (element ** (self.indice))
108                prodfacteurs = produitfacteurs(facteurs)
109                detail.append(' = ')
110                detail.append(str(coeff) + ' \\times ' + racine + prodfacteurs + '}')
111        if radicande == 1:
112            return (coeff, detail)
113        else:
114            return (Racine(radicande, coeff, self.indice), detail)
115
116def simplifie_racine(n):
117    '''renvoie coeff,radicande où sqrt(n)=coeff*sqrt(radicande)'''
118    if n == 0:
119        return 0, 0
120    else:
121        ncar = carrerise(n)
122        return int(sqrt(n // ncar)), ncar
123
124
125def pTeX(n):
126    """renvoie (n) si n<0"""
127    if n < 0:
128        return "(" + decimaux(n) + ")"
129    else:
130        return decimaux(n)
131
132def tTeX(n):
133    if n == 1:
134        return ""
135    elif n == -1:
136        return "-"
137    elif n >= 0:
138        return "+" + decimaux(n)
139    else:
140        return decimaux(n)
141
142
143
144class RacineDegre2:
145    def __init__(self, numerateur=0, denominateur=1, coeff=1, radicande=0):
146        """Constructeur de la forme (a+c*racine(d))/b"""
147        self.numerateur = numerateur  # a
148        self.denominateur = denominateur  # b
149        self.coeff = coeff  # c
150        self.radicande = radicande  # d
151
152    def __str__(self):
153        if isinstance(self.numerateur, str):
154            # utilisé dans le détail de la simplification
155            numerateur = self.numerateur
156        else:
157            numerateur = decimaux(self.numerateur) * (self.numerateur != 0)  # renvoie "" si self.numerateur=0
158        if self.radicande != 0:
159            if isinstance(self.coeff, str):  # utilisé dans le détail de la simplification
160                if self.coeff[0] != "-" and self.coeff[0] != "+":
161                    numerateur += "+"
162                numerateur += self.coeff + "\\sqrt{" + decimaux(self.radicande) + "}"
163            elif self.coeff == 1:
164                numerateur += "+\\sqrt{" + decimaux(self.radicande) + "}"
165            elif self.coeff == -1:
166                numerateur += "-\\sqrt{" + decimaux(self.radicande) + "}"
167            else:
168                numerateur += tTeX(self.coeff) + "\\sqrt{" + decimaux(self.radicande) + "}"
169        if numerateur == '':
170            numerateur = '0'
171        if self.denominateur == 1:
172            result = numerateur
173        else:
174            result = "\\dfrac{%s}{%s}" % (numerateur, self.denominateur)
175
176        if result[0] == '+':
177            return result[1:]
178        else:
179            return result
180
181    def simplifie(self, detail=False):
182        liste_detail = []
183        coeff, radicande = simplifie_racine(self.radicande)
184        numerateur = self.numerateur
185        if self.radicande != 0:
186            if self.coeff == 1:
187                    det_coeff = "+ "
188            elif self.coeff == -1:
189                det_coeff = "- "
190            else:
191                det_coeff = "%s\\times " % (self.coeff)
192            if coeff != 1 or radicande == 1:
193                det_coeff += str(coeff)
194        else:
195            det_coeff = "0"
196        if radicande == 1:
197            # det_coeff="%s\\times%s"%(tTeX(self.coeff),coeff)
198            liste_detail.append("\\dfrac{%s %s}{%s}" % \
199                                    (self.numerateur, det_coeff , self.denominateur))
200            radicande = 0
201            numerateur = self.numerateur + (self.coeff) * int(coeff)
202            coeff = 0
203
204        if coeff != 1:
205            liste_detail.append(str(RacineDegre2(numerateur,
206                                                 self.denominateur,
207                                                 det_coeff,
208                                                 radicande)))
209
210        coeff = (self.coeff) * int(coeff)
211
212        simplifie = pgcd(pgcd(coeff, numerateur), self.denominateur)
213        numerateur = numerateur // simplifie
214        coeff = coeff // simplifie
215        denominateur = self.denominateur // simplifie
216        if simplifie != 1:
217            if radicande != 0 or denominateur != 1:
218                det_numerateur = "%s_{\\times %s}" % (numerateur, pTeX(simplifie))
219                det_denominateur = "%s_{\\times %s}" % (denominateur, pTeX(simplifie))
220                det_coeff = "%s_{\\times %s}" % (coeff, pTeX(simplifie))
221                liste_detail.append(str(RacineDegre2(det_numerateur, det_denominateur, det_coeff, radicande)))
222            liste_detail.append(str(RacineDegre2(numerateur, denominateur, coeff, radicande)))
223        if detail:
224            return RacineDegre2(numerateur, denominateur, coeff, radicande), liste_detail
225        return RacineDegre2(numerateur, denominateur, coeff, radicande)
226
227    def __add__(self, other):
228        if isinstance(other, RacineDegre2):
229            if self.radicande == other.radicande or self.radicande == 0 or other.radicande == 0:
230                radicande = max(self.radicande, other.radicande)
231                premier, second = self, other
232            else:
233                premier = self.simplifie()
234                second = other.simplifie()
235                if self.radicande == other.radicande or self.radicande == 0 or other.radicande == 0:
236                    radicande = max(self.radicande, other.radicande)
237                else:
238                    return NotImplemented
239
240            denominateur = ppcm(premier.denominateur, second.denominateur)
241            facteur1 = denominateur / premier.denominateur
242            facteur2 = denominateur / second.denominateur
243            # if self.radicande==other.radicande:
244            coeff = premier.coeff * facteur1 * (premier.radicande != 0) + second.coeff * facteur2 * (second.radicande != 0)
245            if coeff == 0:
246                radicande = 0
247            return RacineDegre2(premier.numerateur * facteur1 + second.numerateur * facteur2,
248                                denominateur,
249                                coeff,
250                                radicande)
251        elif isinstance(other, int):
252            return self +RacineDegre2(other)
253        elif isinstance(other, Fraction):
254            return self +RacineDegre2(other.numerateur, other.denominateur)
255
256    def __radd__(self, other):
257        return self +other
258    def __neg__(self):
259        return RacineDegre2(-self.numerateur, self.denominateur, -self.coeff, self.radicande)
260
261    def __sub__(self, other):
262        return self +(-other)
263
264    def __rsub__(self, other):
265        return -self + other
266
267    def __mul__(self, other):
268        if isinstance(other, Fraction):
269            return self * RacineDegre2(other.numerateur, other.denominateur, 0, self.radicande)
270        elif isinstance(other, int):
271            return self * RacineDegre2(other, 1, 0, self.radicande)
272        else:
273            radicande = max(self.radicande, other.radicande)  # cela autorise d'avoir un radicande=0 mais n'efface pas l'autre
274            coeff = self.numerateur * (other.coeff * (other.radicande != 0)) + (self.coeff * (self.radicande != 0)) * other.numerateur
275            if coeff == 0:
276                radicande = 0
277            numerateur = self.numerateur * other.numerateur + (self.coeff * other.coeff) * (not(self.radicande == 0 or other.radicande == 0)) * self.radicande
278            return RacineDegre2(numerateur,
279                            self.denominateur * other.denominateur,
280                            coeff,
281                            radicande)
282    def __invert__(self):
283        return self.denominateur * RacineDegre2(self.numerateur, self.numerateur ** 2 - self.coeff ** 2 * self.radicande, -self.coeff, self.radicande)
284    def __div__(self, other):
285        return self * ~other
286    def __rdiv__(self, other):
287        return ~self * other
288    def __rmul__(self, other):
289        return self * other
290    def __pow__(self, n):
291        result = 1
292        for dummy in range(n):
293            result = result * self
294        return result
295    def __float__(self):
296        return (self.numerateur + self.coeff * sqrt(self.radicande)) / self.denominateur
297    def __cmp__(self, other):
298        comp = float(self) - float(other)
299        if comp > 0:
300            return 1
301        elif comp < 0:
302            return -1
303        else:
304            return 0
Note: See TracBrowser for help on using the repository browser.