#!/usr/bin/env python3
# Pyromaths
# Un programme en Python qui permet de créer des fiches d'exercices types de
# mathématiques niveau collège ainsi que leur corrigé en LaTeX.
# Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
from pyromaths.outils.decimaux import decimaux
from pyromaths.outils import Priorites3
from pyromaths.classes.SquareRoot import SquareRoot
from pyromaths.classes.Fractions import Fraction
from random import *
from functools import reduce
[docs]class Polynome:
""" Cette classe crée la notion de polynômes.
Si ``var == None`` alors la variable est ``x``.
*details* donne le niveau de détails attendus dans les développements et réductions :
- 0 : pas de détails : 3x+4x => 7x
- 1 : ordonne avant de réduire
- 2 : ordonne puis factorise les réductions : 3x+4x=(3+4)x
- 3 : comme 2 et détaille les produits : 2x*3x=2*3*x*x
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome([[2,2],[3,1],[4,0]], 'z'))
Polynome([[2, 2], [3, 1], [4, 0]], "z", 0)
>>> repr(Polynome("2y^2+3y+4"))
Polynome([[2, 2], [3, 1], [4, 0]], "y", 0)
>>> repr(Polynome([[1, 1], [2, 2]]))
Polynome([[1, 1], [2, 2]], "x", 0)
>>> repr(Polynome("Fraction(1,7)x^2-Fraction(3,8)x-1"))
Polynome([[Fraction(1, 7), 2], [Fraction(-3, 8), 1], [-1, 0]], "x", 0)
"""
[docs] def __init__(self, monomes, var=None, details=0):
"""Crée un polynôme."""
monomes = monomes or '0' # monômes du polynôme, par défaut un polynôme nul
if isinstance(monomes, Polynome):
self.monomes = monomes.monomes
self.var = monomes.var
self.details = monomes.details
elif isinstance(monomes, str):
# Gère la construction des polynôme à partir d'une chaîne de caractères
self.details = details
listmonomes = []
splitted = Priorites3.splitting(monomes)
m_coef, var, coef = None, None, ''
while splitted:
extract = splitted.pop(0)
if extract in '+-':
if m_coef:
listmonomes.append([m_coef, 0])
m_coef = None
coef = extract
elif Priorites3.EstNombre(extract):
m_coef = eval(coef + extract)
else:
if var and extract != var:
raise ValueError(u'Le nom de la variable (%s) est incorrect pour le Polynôme %s' % (var, monomes))
if var is None: var = extract
if splitted and splitted[0] == '^':
splitted.remove('^')
m_deg = eval(splitted.pop(0))
else:
m_deg = 1
if m_coef is None:
if coef == '-':
m_coef = -1
else:
m_coef = 1
listmonomes.append([m_coef, m_deg])
m_coef = None
if m_coef: listmonomes.append([m_coef, 0])
if listmonomes: self.monomes = listmonomes
else: self.monomes = [[0, 0]]
self.var = var or 'x'
else:
# Supprime les monomes nuls :
for k in range(len(monomes) - 1, -1, -1):
if monomes[k][0] == 0: monomes.pop(k)
if not monomes: monomes = [[0, 0]]
self.monomes = monomes
self.var = var or 'x' # Variable par défaut
self.details = details
[docs] def __repr__(self):
"""**repr**\ (*object*)
Renvoie une chaîne de caractère représentant un :mod:`Polynome`
évaluable pour créer un :mod:`Polynome`.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome([[2,2],[3,1],[4,0]], 'z'))
Polynome([[2, 2], [3, 1], [4, 0]], "z", 0)
:rtype: string
"""
return "Polynome(%s, \"%s\", %s)" % (self.monomes, self.var, self.details)
[docs] def __str__(self):
r"""**str**\ (*object*)
Renvoie une version LaTeX du polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> str(Polynome([[2,2],[3,1],[4,0]], 'z'))
2\,z^{2}+3\,z+4
>>> str(Polynome("y^2-Fraction(3,2)y-1"))
y^{2}-\dfrac{3}{2}\,y-1
>>> from pyromaths.classes.Fractions import Fraction
>>> Polynome([[1, 1], [Fraction(-5, 1), 0]])
x-5
:rtype: string
"""
def print_coef(coef):
"""Gère le format du coef
"""
if isinstance(coef, (float, int)):
if coef > 0: return "+" + decimaux(coef)
else: return decimaux(coef)
if isinstance(coef, Fraction):
if isinstance(coef.n, int) and isinstance(coef.d, int) and coef.n < 0 and coef.d > 0:
return "-" + str(Fraction(-coef.n, coef.d, coef.code))
return "+" + str(coef)
if isinstance(coef, SquareRoot):
if len(coef) > 1: coef = str(coef)
else:
if coef[0][0] > 0:
return '+' + str(coef)
else:
return str(coef)
if isinstance(coef, str):
texte = "(" + "".join(Priorites3.texify([Priorites3.splitting(coef)])) + ")"
if texte[0] != "-": return "+" + texte
else: return texte
raise ValueError(u'Not Implemented : Coefficient %s' % coef)
var = self.var
s = ""
for m in self.monomes:
if isinstance(m, list):
if m[1] > 1:
# Monôme de degré au moins 2
if m[0] == 1:
s = s + "+" + var + "^{" + str(m[1]) + "}"
elif m[0] == -1:
s = s + "-" + var + "^{" + str(m[1]) + "}"
else:
s = s + print_coef(m[0]) + r"\," + var + "^{" + str(m[1]) + "}"
elif m[1] == 1:
# Monôme de degré 1
if m[0] == 1:
s = s + "+" + var
elif m[0] == -1:
s = s + "-" + var
else:
s = s + print_coef(m[0]) + r"\," + var
else:
# Monôme de degré 0
s = s + print_coef(m[0])
# supprime le + en début de séquence
s = s.lstrip("+")
if not s: s = "0"
return s
[docs] def __call__(self, valeur):
"""**__call__**\ (*object*\ ,*valeur*)
``p.__call__(valeur)`` est équivalent à ``p(valeur)``
Retourne l'expression numérique du polynôme pour sa variable égale à
valeur.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome("4+x-x^2+x^3-2x^5")(-5)
4-5-(-5)**2+(-5)**3-2*(-5)**5
:param: valeur
:type: integer, float or Fraction
:rtype: string
"""
if Polynome.degre(self) == 0:
return self.monomes[0][0] or '0'
if valeur == 0:
retour = ''
for m in self.monomes:
if m[1] == 0: retour += '+%r' % m[0]
return retour.lstrip('+').replace('+-', '-') or '0'
if valeur < 0 and isinstance(valeur, (float, int)): nb = "(%s)" % valeur
else: nb = repr(valeur)
retour = ''
for m in self.monomes:
if m[1] == 0: retour += '+%r' % m[0]
elif m[1] == 1:
if m[0] == 1:
retour += '+%r' % valeur
elif m[0] == -1:
retour += '-' + nb
else:
retour += '+%r*' % m[0] + nb
else:
if m[0] == 1:
retour += '+' + nb + '**%s' % m[1]
elif m[0] == -1:
retour += '-' + nb + '**%s' % m[1]
else:
retour += '+%r*' % m[0] + nb + '**%s' % m[1]
return retour.lstrip('+').replace('+-', '-')
def derive(self):
if Polynome.degre(self) < 1:
return Polynome([0, 0], self.var, self.details)
else:
p = []
for m in self:
if m[1] > 0:
p.append([m[0] * m[1], m[1] - 1])
return Polynome(p, self.var, self.details)
[docs] def __getitem__(self, i):
"""*object*\ .\ **__getitem__**\ (*integer*)
Renvoie le i ème monome du polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome("2y+3y^2+4")[1]
[3, 2]
:rtype: list
"""
return self.monomes[i]
[docs] def __delitem__(self, i):
"""*object*\ .\ **__delitem__**\ (*integer*)
Renvoie le polynôme privé du i ème monome.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> p = Polynome("2y+3y^2+4")
>>> del p[1]
>>> repr(p)
Polynome([[2, 1], [4, 0]], "y", 0)
:rtype: Polynome
"""
m = self.monomes
del m[i]
return Polynome(m, self.var, self.details)
[docs] def __iadd__(self, other):
"""*object*\ .\ **__iadd__**\ (*other*)
``p.__iadd__(q)`` est équivalent à ``p += q``
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> p=Polynome("2y+3y^2+4")
>>> p += Polynome('-y+6')
>>> repr(p)
Polynome([[2, 1], [3, 2], [4, 0], [-1, 1], [6, 0]], "y", 0)
:rtype: Polynome
"""
other = self._convert_other(other)
m1, m2 = [m for m in self.monomes], [m for m in other.monomes]
m = []
m1.extend(m2)
for monomes in m1:
if monomes[0]: m.append(monomes)
return Polynome(m, self.var, self.details)
[docs] def __eq__(self, other):
"""*object*\ .\ **__eq__**\ (*other*)
``p.__eq__(q)`` est équivalent à ``p == q``
Renvoie True si deux polynômes sont égaux. Ne tient pas compte de
l'ordre des monômes.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome("2y+3y^2+4") == Polynome('-y+6')
False
>>> Polynome('3x+5x+4')== Polynome('8x+4')
False
:rtype: boolean
"""
other = self._convert_other(other)
return sorted(self.monomes, key=lambda x: (-x[1], x[0])) == \
sorted(other.monomes, key=lambda x: (-x[1], x[0]))
[docs] def __ne__(self, other):
"""*object*\ .\ **__ne__**\ (*other*)
``p.__ne__(q)`` est équivalent à ``p != q``
Renvoie True si deux polynômes sont différents. Ne tient pas compte de
l'ordre des monômes.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome("2y+3y^2+4") != Polynome('-y+6')
True
:rtype: boolean
"""
return not (self == other)
[docs] def __add__(self, *others):
"""*object*\ .\ **__add__**\ (*\ \*others*)
``p.__add__(q)`` est équivalent à ``p + q`` calcule la somme de
polynômes.
*other* peut être une chaîne représentant un polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome("2y+3y^2+4", details=2)+Polynome('-y+6', details=2))
Polynome([[3, 2], [2, 1], [-1, 1], [4, 0], [6, 0]], "y", 2)
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: Polynome
"""
# if isinstance(other, str):
# other = eval(other)
for other in others:
other = self._convert_other(other)
self +=other
return self.nreduction()
[docs] def __radd__(self, other):
"""*object*\ .\ **__radd__**\ (*other*)
``p.__radd__(q)`` est équivalent à ``q + p``
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> from pyromaths.classes.Fractions import Fraction
>>> repr(Fraction(5,4)+Polynome("3x"))
Polynome([[3, 1], [Fraction(5, 4), 0]], "x", 0)
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: Polynome
"""
if isinstance(other, str):
other = eval(other)
other = self._convert_other(other)
return other + self
[docs] def __sub__(self, *others):
"""*object*\ .\ **__sub__**\ (*other*)
``p.__sub__(q)`` est équivalent à ``p + q`` calcule la somme de
polynômes.
*other* peut être une chaîne représentant un polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome("2y+3y^2+4")-Polynome('-y+6'))
'Polynome([[2, 1], [3, 2], [4, 0]], "y", 0)+Polynome([[1, 1], [-6, 0]], "y", 0)'
>>> repr(Polynome("3y^2+2y+4")-Polynome('-y+6'))
'Polynome([[3, 2], [2, 1], [4, 0]], "y", 0)+Polynome([[1, 1], [-6, 0]], "y", 0)'
>>> repr(Polynome("x+6")-Polynome("3x"))
Polynome([[-2, 1], [6, 0]], "x", 0)
>>> repr(Polynome("x+6",details=2)-Polynome("3x",details=2))
Polynome([[1, 1], [-3, 1], [6, 0]], "x", 2)
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: Polynome or string
"""
areduire = False
if self.ordonne().reductible(): areduire = True
lother = []
details, etapes = self.details, False
for other in others:
other = self._convert_other(other)
if other == 0:
pass
else:
if other.ordonne().reductible(): areduire = True
details = min(details, other.details)
if len(other) > 1: etapes = True
lother.append(other)
if areduire:
lother = [other.nreduction() for other in lother]
lother.insert(0, self.nreduction())
return "-".join([repr(other) for other in lother])
else:
calcul = "%r+" % self +"+".join([repr(-other) for other in lother])
if etapes: return calcul
else: return eval(calcul)
[docs] def __rsub__(self, other):
"""*object*\ .\ **__rsub__**\ (*other*)
``p.__rsub__(q)`` est équivalent à ``q - p``
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(1-Polynome([[-4, 1], [-9, 2], [-5, 0]], "x"))
'Polynome([[1, 0]], "x", 0)+Polynome([[4, 1], [9, 2], [5, 0]], "x", 0)'
>>> from pyromaths.classes.Fractions import Fraction
>>> repr(Fraction(5,4)-Polynome("3x"))
Polynome([[-3, 1], [Fraction(5, 4), 0]], "x", 0)
>>> repr(Fraction(5,4)-Polynome("-3x"))
Polynome([[3, 1], [Fraction(5, 4), 0]], "x", 0)
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: Polynome
"""
other = self._convert_other(other)
if len(self) == 1:
# Cas où on soustrait un polynôme de longueur 1
other += -self
return other.ordonne()
return "%r+%r" % (other, -self)
[docs] def __neg__(self):
"""*object*\ .\ **__neg__**\ ()
``p.__neg__()`` est équivalent à ``-p`` est équivalent à ``p = -p``
**TODO :** Corriger ce dernier point ; p ne devrait pas être modifié
Renvoie l'opposé d'un polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(-Polynome("2y+3y^2+4"))
Polynome([[-2, 1], [-3, 2], [-4, 0]], "y", 0)
:rtype: Polynome
"""
if self.ordonne().reductible(): return '-%r' % self.nreduction()
m = [m1 for m1 in self.monomes]
for i in range(len(m)):
m[i][0] = -m[i][0]
return Polynome(m, self.var, self.details)
[docs] def __pos__(self):
"""*object*\ .\ **__pos__**\ ()
``p.__pos__()`` est équivalent à ``+p``
Renvoie le polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(+Polynome("2y+3y^2+4"))
Polynome([[2, 1], [3, 2], [4, 0]], "y", 0)
:rtype: Polynome
"""
return self
[docs] def __mul__(self, *others):
"""*object*\ .\ **__mul__**\ (*other*)
``p.__mul__(q)`` est équivalent à ``p * q``
Renvoie une chaîne de caractère ou un objet Polynôme dont les éléments
sont :
* le produit de ``p`` et ``q`` si ce sont deux monômes dont un au moins
a pour coefficient 1.
* le produit détaillé de ``p`` et ``q`` si ce sont deux monômes ne
dépendant pas du cas précédent.
* le développement par distributivité dans les autres cas
si details est égal à 0, les produits dans les distributivités sont calculés immédiatement,
sinon les produits sont explicités.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome('3x+4', details=0)*Polynome('2x+5', details=0))
'Polynome([[6, 2]], "x", 0)+Polynome([[15, 1]], "x", 0)+Polynome([[8, 1]], "x", 0)+Polynome([[20, 0]], "x", 0)'
>>> repr(Polynome('3x', details=1)*Polynome('2x+5', details=1))
'Polynome([[3, 1]], "x", 1)*Polynome([[2, 1]], "x", 1)+Polynome([[3, 1]], "x", 1)*Polynome([[5, 0]], "x", 1)'
>>> repr(Polynome('3x', details=3) * Polynome('2x', details=3))
"Polynome([[3, 0]], var = 'x', details=3)*Polynome([[1, 1]], var = 'x', details=3)*Polynome([[2, 0]], var = 'x', details=3)*Polynome([[1, 1]], var = 'x', details=3)"
>>> repr(Polynome('3', details=3)*Polynome('x', details=3))
Polynome([[3, 1]], "x", 3)
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: string ou Polynome
"""
def id_rem(p1, p2):
'''Renvoie 1, 2 ou 3 selon l'identité remarquable trouvée, None sinon'''
if len(p1) != 2 or len(p2) != 2: return None
p1, p2 = p1.ordonne(), p2.ordonne()
m0 = [abs(p1[0][0]), p1[0][1]]
m1 = [abs(p1[1][0]), p1[1][1]]
if p1 == p2:
# 1ère ou 2ème identité remarquable
return p1 ** 2
if (p1[0][1] == p2[0][1] and p1[1][1] == p2[1][1]) and (p1[0][0] == p2[0][0] and\
p1[1][0] == -p2[1][0]) or (p1[0][0] == -p2[0][0] and p1[1][0] == p2[1][0]):
# 3ème identité remarquable
if p1[0][0] == p2[0][0]:
poly = "%r**2-%r**2" % (Polynome([p1[0]], self.var, self.details), \
Polynome([m1], self.var, self.details))
else:
poly = "%r**2-%r**2" % (Polynome([p1[1]], self.var, self.details), \
Polynome([m0], self.var, self.details))
return poly
return None
if self == 0: return 0
lother = [self] + list(others)
for el in lother:
if el.ordonne().reductible():
# On commence par réduire la chaîne
return "*".join([repr(other.nreduction()) for other in lother])
lcoeff, lexp, reduire, ordonne = [], [], True, True
for i in range(len(lother)):
lother[i] = self._convert_other(lother[i])
if len(lother[i]) == 1:
# c'est un monôme, il est donc probablement réduit
coeff, exp = lother[i][0][0], lother[i][0][1]
if coeff != 1: lcoeff.append(coeff)
if exp != 0: lexp.append(exp)
if coeff != 1 and exp != 0: reduire = False
if lexp and exp < lexp[-1]: ordonne = False
if lother[i] == 0: return 0
if len(lother[i]) > 1 or i + 1 == len(lother):
# Ce n'est pas un monôme, il va donc falloir utiliser la distributivité
# ou alors la chaine est fini et on calcule
if i > 1 or len(lother[i]) == 1 or len(lcoeff) > 1 or len(lexp) > 1:
# on a multiplié au moins 2 monômes auparavant
if lother[i].details == 3 and not reduire:
# TODO: cas où un coeff est une str
#=======================================================
# return "*".join([repr(coeff) for coeff in lcoeff]) + "*" + \
# "*".join(["Polynome([[1, %s]], '%s', %s)" % (exp, self.var, self.details) for exp in lexp]) + \
# "*".join([repr(other.nreduction()) for other in lother[i + 1:]])
#=======================================================
produit = []
for j in lother:
if j[0][0] != 1 and j[0][1] > 0:
produit.append("*".join(['Polynome([[%s, 0]], var = \'%s\', details=%s)' % (j[0][0], j.var, j.details), \
'Polynome([[1, %s]], var = \'%s\', details=%s)' % (j[0][1], j.var, j.details)]))
else:
produit.append(repr(j))
return "*".join(produit)
if lother[i].details == 3 and not ordonne:
coeff = "*".join([repr(coeff) for coeff in lcoeff])
if coeff: sol = [coeff]
else: sol = []
exp = "*".join(["Polynome([[1, %s]], '%s', %s)" % (exp, self.var, self.details) for exp in lexp])
if exp: sol.append(exp)
if lother[i + 1:]: sol.append("*".join([repr(other.nreduction()) for other in lother[i + 1:]]))
return "*".join(sol)
else:
lcoeff.append(1)
lexp.append(0)
poly = Polynome([[reduce(lambda x, y: x * y, lcoeff), \
reduce(lambda x, y: x + y, lexp)]], self.var, self.details)
if i + 1 == len(lother): return poly
else: return \
"*".join([repr(poly)] + [repr(other.nreduction()) for other in lother[i:]])
else:
# On distribue :
if i:
# on va utiliser la distributivité simple
poly = Polynome([[coeff, exp]], self.var, self.details)
if self.details > 0:
produit = "+".join([repr(poly) + "*" + repr(Polynome([other], self.var, self.details)) for other in lother[i]])
if i + 1 < len(lother): produit = "(" + produit + ")"
return "*".join([produit] + [repr(other.nreduction()) for other in lother[i + 1:]])
else:
produit = "+".join([repr(Polynome([[poly[0][0] * other[0], poly[0][1] + other[1]]], self.var, self.details)) for other in lother[i]])
if i + 1 < len(lother): produit = "(" + produit + ")"
return "*".join([produit] + [repr(other.nreduction()) for other in lother[i + 1:]])
else:
# le premier polynome est de longueur au moins 2
produit = id_rem(lother[0], lother[1])
if produit == None:
# Distributivité
# TODO: Convertir (a-b) en (a+(-b)) pour details=3
#===================================================
# if self.details == 3:
# difference, produit = False, []
# for poly in lother:
# if len(poly) > 1:
# for j in range(1, len(poly)):
# if poly[j][0] < 0:
# difference = True
# produit.append("(" + "+".join(['Polynome(%s, var = \'%s\', details=%s)' % (poly[i], poly.var, poly.details) for i in range(len(poly))]) + ")")
# break
# if not difference: produit.append(repr(poly))
# if difference:
# return "*".join(produit)
#===================================================
if self.details > 0:
produit = "+".join(["+".join([repr(Polynome([premier], self.var, self.details)) + \
"*" + repr(Polynome([second], self.var, self.details)) \
for second in lother[1]]) for premier in lother[0]])
if i + 2 < len(lother): produit = "(" + produit + ")"
return "*".join([produit] + [repr(other.nreduction()) for other in lother[i + 2:]])
else:
produit = "+".join(["+".join([repr(Polynome([[premier[0] * second[0], premier[1] + second[1]]], self.var, self.details)) \
for second in lother[1]]) for premier in lother[0]])
if i + 2 < len(lother): produit = "(" + produit + ")"
return "*".join([produit] + [repr(other.nreduction()) for other in lother[i + 2:]])
else:
# identité remarquable
if i + 2 < len(lother): produit = "(" + produit + ")"
return "*".join([produit] + [repr(other.nreduction()) for other in lother[i + 2:]])
[docs] def __rmul__(self, other):
"""Multiplication de *other* (qui n'est pas un polynôme) par *self*
(qui en est un)
* Si *other* est une suite de produits de monômes, et *self* un polynôme
de rang 1, on effectue toutes les multiplications en une fois
* Sinon, on calcule d'abord @other
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: string ou Polynome"""
if isinstance(other, (int, float, Fraction)):
other = self._convert_other(other)
return other * self
if isinstance(other, str):
from pyromaths.outils.Priorites3 import splitting
ls = splitting(other)
if ls.count("+") or ls.count("-"):
# Réduire @other avant de faire le produit et vérifier s'il faut
# des parenthèses autour de l'expression @other
par, besoin = 0, False
for k in range(len(ls)):
if ls[k] == "(": par += 1
elif ls[k] == ")": par -= 1
elif not par and ls[k] in "+-":
besoin = True
break
if besoin: return "(" + other + ")*" + repr(self)
else: return other + "*" + repr(self)
elif len(self) > 1:
return other + "*" + repr(self)
else:
index = 0
for i in range(len(ls)):
if "Polynome(" in ls[i]:
if len(eval(ls[i])) > 1:
return other + "*" + repr(self)
elif Polynome.degre(eval(ls[i])) > 0:
index = index or i
index = index or len(ls)
if self.monomes[0][0] != 1:
ls.insert(index, "*")
if self.monomes[0][0] < 0: ls.insert(index, "(" + repr(self.monomes[0][0]) + ", %s)" % self.details)
else: ls.insert(index, repr(self.monomes[0][0]))
if self.monomes[0][1] > 0:
ls.append("*")
ls.append("Polynome([%s], \"%s\", %s)" % ([1, self.monomes[0][1]], self.var, self.details))
return "".join(ls)
else: raise ValueError(u"Type non prévu. Bogue en perspective !")
def _divide(self, other):
"""*object*\ .\ **div**\ (*other*)
``p.__truediv__(q)`` est équivalent à ``p / q``
Renvoie (self // other, self % other) deux polynomes où le premier élément est le quotient et le second
le reste de la division euclidienne de self par other.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome('3x+4', 0)._divide(Polynome('2x+5', 0))
(Polynome([[Fraction(3, 2), 0]], "x", 0), Polynome([[Fraction(-7, 2), 0]], "x", 0))
>>> Polynome("x^4+2x^3+3x^2+5x+6")._divide(Polynome("7x+8"))
(Polynome([[Fraction(1, 7), 3], [Fraction(6, 49), 2], [Fraction(99, 343), 1], [Fraction(923, 2401), 0]], "x", 0), Polynome([[Fraction(7022, 2401), 0]], "x", 0))
:param: other
:type: Polynome ou string *évaluable comme Polynome*
:rtype: Deux Polynome
"""
other = self._convert_other(other)
quotient = Polynome([], self.var, self.details)
reste = Polynome.ordonne(self)
diviseur = other.ordonne()
degre_diviseur = diviseur.degre()
while reste.degre() >= degre_diviseur:
degre = reste.degre() - degre_diviseur
if isinstance(reste[0][0], Fraction) or isinstance(diviseur[0][0], Fraction):
coef = eval(Priorites3.priorites('%r/%r' % (reste[0][0], diviseur[0][0]))[-1][0])
else:
if reste[0][0] % diviseur[0][0]:
coef = Fraction(reste[0][0], diviseur[0][0])
else:
coef = reste[0][0] // diviseur[0][0]
quotient.monomes.append([coef, degre])
reste = eval(Priorites3.priorites('%r-Polynome([[%r, %s]], "%s", %s)*%r' % (reste, coef, degre, self.var, self.details, diviseur))[-1][0])
return quotient.nreduction(True), reste
[docs] def __mod__(self, other):
"""
self % other
"""
other = self._convert_other(other)
if other is NotImplemented:
return other
if not other:
if self:
raise ValueError(u'Opération non valide : x % 0')
else:
raise ValueError(u'Division non définie : 0 % 0')
return self._divide(other)[1]
[docs] def __floordiv__(self, other):
"""
self // other
"""
other = self._convert_other(other)
if other is NotImplemented:
return other
if not other:
if self:
raise ValueError(u'Opération non valide : x // 0')
else:
raise ValueError(u'Division non définie : 0 // 0')
return self._divide(other)[0]
[docs] def __len__(self):
"""*object*\ .\ **__len__**\ ()
``p.__len__()`` équivaut à ``len(p)`` et renvoie le nombre de monômes d'un polynôme.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> len(Polynome("2y+3y^2+4"))
3
:rtype: integer
"""
m = [m1 for m1 in self.monomes]
m = Polynome.ordonne(Polynome(m, self.var))
return len(self.monomes)
[docs] def degre(self):
"""**degre**\ (*object*)
Retourne le degré d'un polynôme, -1 pour le polynôme nul
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome("2y+3y^2+4").degre()
2
>>> Polynome('').degre()
-1
:rtype: integer
"""
if self == 0: return -1
else: return self.nreduction(True)[0][1]
[docs] def __pow__(self, other):
"""*object*\ .\ **pow**\ (*integer*)
``p.__pow__(n)`` équivaut à ``p**n`` et renvoie le développement du
polynôme p à la puissance n.
* Si ``n == 1``, alors renvoie l'objet Polynome ;
* si ``n == 2``, alors renvoie une chaîne avec le développement en
utilisant une identité remarquable ;
* si ``n > 1``, renvoie le développement en utilisant la formule du
binôme de Newton.
**TODO :** si ``n == 2`` et ``len(p) > 2``, bug
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome("2y+4")**2)
'Polynome([[2, 1]], "y", 0)**2+2*Polynome([[2, 1]], "y", 0)*Polynome([[4, 0]], "y", 0)+Polynome([[4, 0]], "y", 0)**2'
>>> repr(Polynome("2y")**3)
Polynome([[8, 3]], "y", 0)
:rtype: string ou Polynome
"""
if len(self) == 2 and other == 2:
a0 = self.monomes[0][0]
b0 = self.monomes[1][0]
p = a0 * b0
a = Polynome([[abs(a0), self.monomes[0][1]]], self.var, self.details)
b = Polynome([[abs(b0), self.monomes[1][1]]], self.var, self.details)
if p < 0:
return "%r**2-2*%r*%r+%r**2" % (a, a, b, b)
else:
return "%r**2+2*%r*%r+%r**2" % (a, a, b, b)
elif len(self) == 1:
return Polynome([[self[0][0] ** other, self[0][1] * other]], self.var)
else:
result = self
for dummy in range(other - 1):
result = eval(result * self)
return result
[docs] def reductible(self):
"""**reductible**\ (*object*)
Retourne True si le polynôme est réductible ou ordonnable, False sinon.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> Polynome([[2, 1], [3, 2], [4, 0], [-1, 1], [6, 0]], "y").reductible()
True
:param type: Polynome
:rtype: boolean
"""
#=======================================================================
# if self != self.reduit():
# return True
# else:
# return False
#=======================================================================
ldegres = []
for m in self:
if m[1] in ldegres: return True
# Il existe déjà un monome de même degré, le polynome est donc réductible.
elif ldegres and m[1] > ldegres[-1]: return True
# Polynome non ordonné
else: ldegres.append(m[1])
if isinstance(m[0], str) and Priorites3.effectue_calcul(Priorites3.splitting(m[0])) != [m[0]]: return True
if isinstance(m[0], Fraction) and repr(m[0].traitement(True)) != repr(m[0]): return True
if isinstance(m[0], SquareRoot) and repr(m[0].simplifie()) != repr(m[0]): return True
# une simplification de fraction ou un calcul est à faire
return False
[docs] def ordonnable(self):
"""**ordonnable**\ (*object*)
Retourne True si le polynome n'est pas ordonnée, False sinon.
:param type: Polynome
:rtype: boolean
"""
lastdegre = None
for m in self:
if lastdegre is not None and m[1] > lastdegre: return True
else: lastdegre = m[1]
return False
[docs] def ordonne(self):
"""**ordonne**\ (*object*)
Retourne une version ordonnée d'un polynome en écrivant en premier les
monômes de degré supérieur.
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> repr(Polynome([[2, 1], [3, 2], [4, 0], [-1, 1], [6, 0]], "y").ordonne())
Polynome([[3, 2], [2, 1], [-1, 1], [4, 0], [6, 0]], "y", 0)
:param type: Polynome
:rtype: Polynome
"""
# if len(self) == 1: return self
m1 = self.monomes
m1 = sorted(m1, key=lambda x: (-x[1]))
return Polynome(m1, self.var, self.details)
[docs] def nreduction(self, bdirecte=False):
"""**nreduction**\ (*object*)
Retourne une étape de la réduction d'un polynome selon la valeur de *detail*
Si bdirecte est True, alors donne la version réduite sans aucun détail de calcul
:param type: Polynome
:param bdirecte: faut-il donner directement le résultat de la réduction, sans étape de calcul ?
:param type: boolean
:rtype: Polynome
"""
def _reduit_monome(monome, bdirecte):
if isinstance(monome[0], (str, Fraction, SquareRoot)):
# une réduction peut-être à faire ici
if isinstance(monome[0], Fraction):
monome[0] = repr(monome[0].traitement(True))
res = []
elif isinstance(monome[0], SquareRoot):
monome[0] = repr(monome[0].simplifie())
res = []
else:
splitted = Priorites3.splitting(monome[0])
if len(splitted) > 1:
res = Priorites3.effectue_calcul(splitted)
if len(res) == 1: # Le calcul s'effectue en une seule étape
monome[0] = res[0]
if len(res) > 1:
# Il y a un calcul à effectuer en plusieurs étapes
if bdirecte: # on ne détaille pas
monome[0] = eval(Priorites3.priorites(monome[0])[-1][0])
else:
bdec = True
# *bdec* est un booléen qui est True si le calcul ne contient que des décimaux
for nb in res:
if nb[0] not in "+-*/0123456789(":
bdec = False
break
if bdec: # on calcule en une étape 3+4-5
monome[0] = eval(Priorites3.priorites(monome[0])[-1][0])
else:
monome[0] = ''.join(res) # on calcule étape par étape
else:
monome[0] = eval(monome[0]) # le texte n'était pas nécessaire, c'est un nombre ou la fraction était irréductible
return monome
if not self.reductible(): return self
else:
if self.ordonnable() and self.details > 0 and not bdirecte:
return self.ordonne()
if not self.ordonne().reductible():
# le polynome est seulement ordonnable
return self.ordonne()
# le polynome est donc réductible :
factorisation, bfact = [], False
# *factorisation* est une liste de monomes, qui va contenir les monomes du polynome en cours
# de réduction, en stockant au format texte la somme des coefficients des monomes de même degré
# *bfact* est un booléen qui est vrai si on doit effectuer une factorisation pour réduire le
# polynome
for m in self.ordonne().monomes:
if factorisation and m[1] == factorisation[-1][1]:
# deux monomes de même degré
bfact = True
if not isinstance(factorisation[-1][0], str): factorisation[-1][0] = repr(factorisation[-1][0])
if isinstance(m[0], str):
# On écrit la somme des deux coefficients au format str
factorisation[-1][0] += '+' + m[0]
elif m[0] > 0:
factorisation[-1][0] += '+%r' % m[0]
# On écrit la somme des deux coefficients au format str
elif m[0] < 0:
if isinstance(m[0], Fraction) and isinstance(m[0].d, str):
# On écrit la somme des deux coefficients au format str
factorisation[-1][0] += '+%r' % m[0]
else:
# On écrit la différence des deux coefficients au format str, '2-4'
# plutôt que '2+(-4)'
factorisation[-1][0] += '-%r' % -m[0]
else:
# on ajoute un nouveau monome de degré inférieur au précédent
factorisation.append([m[0], m[1]])
if bfact and self.details > 1 and not bdirecte:
# On retorune le polynome avec les factorisations mises en évidence
# Cas du monome de degré 0
if factorisation[-1][1] == 0 and isinstance(factorisation[-1][0], str):
factorisation[-1] = _reduit_monome(factorisation[-1], bdirecte)
return Polynome(factorisation, self.var, details=self.details)
# on réduit le polynome
for i in range(len(factorisation)):
factorisation[i] = _reduit_monome(factorisation[i], bdirecte)
return Polynome(factorisation, self.var, details=self.details)
# Les monomes nuls sont retirés par la classe Polynome
def _convert_other(self, other):
"""Convertit other en Polynome
Utilisée dans les fonctions d'opérations entre Polynomes :add, sub, mul, ...
"""
if isinstance(other, Polynome):
if self.var == other.var:
return other
else:
raise ValueError(u'Pyromaths ne sait manipuler que deux polynômes de même variable : %s et %s' % (self.var, other.var))
if isinstance(other, (float, int, Fraction)):
return Polynome([[other, 0]], self.var, self.details)
return NotImplemented
def factoriser(calcul):
"""Factorise la somme calcul. Cette procédure n'est ni exaustive, ni
robuste. Elle permet actuellement de résoudre les exercices proposés en 3e.
:param calcul: Expression à factoriser
:type calcul: str
>>> from pyromaths.classes.PolynomesCollege import factoriser
>>> factoriser("Polynome('4x^2+12x+9')")
'Polynome([[2.0, 1]], "x", 0)**2+2*Polynome([[2.0, 1]], "x", 0)*Polynome([[3.0, 0]], "x", 0)+Polynome([[3.0, 0]], "x", 0)**2'
>>> factoriser("Polynome('-4x^2+12x-9')")
'-(Polynome([[2.0, 1]], "x", 0)**2-2*Polynome([[2.0, 1]], "x", 0)*Polynome([[3.0, 0]], "x", 0)+Polynome([[3.0, 0]], "x", 0)**2)'
>>> factoriser("Polynome('4x^2-9')")
'Polynome([[SquareRoot([[1, 4]]), 1]], "x", 0)**2-Polynome([[SquareRoot([[1, 9]]), 0]], "x", 0)**2'
>>> factoriser("Polynome('3x^2-5')")
'Polynome([[SquareRoot([[1, 3]]), 1]], "x", 0)**2-Polynome([[SquareRoot([[1, 5]]), 0]], "x", 0)**2'
>>> factoriser("Polynome('4x^2')")
'Polynome([[2.0, 1]], "x", 0)**2'
>>> factoriser("Polynome('4x')")
>>> factoriser("Polynome('x+1')*Polynome('x+2')+Polynome('x+1')*Polynome('x+3')")
'Polynome([[1, 1], [1, 0]], "x", 0)*(Polynome([[1, 1], [2, 0]], "x", 0)+Polynome([[1, 1], [3, 0]], "x", 0))'
>>> factoriser("Polynome('x+1')*Polynome('x+2')+Polynome('x+1')")
'Polynome([[1, 1], [1, 0]], "x", 0)*Polynome([[1, 1], [2, 0]], "x", 0)+Polynome([[1, 1], [1, 0]], "x", 0)*1'
>>> factoriser("Polynome('x+1')*Polynome('x+2')+Polynome('x+1')**2")
'Polynome([[1, 1], [1, 0]], "x", 0)*Polynome([[1, 1], [2, 0]], "x", 0)+Polynome([[1, 1], [1, 0]], "x", 0)*Polynome([[1, 1], [1, 0]], "x", 0)'
>>> factoriser("Polynome('x+1')**2-Polynome([[81, 0]], 'x', 3)")
'Polynome([[1, 1], [1, 0]], "x", 0)**2-Polynome([[9.0, 0]], "x", 3)**2'
:rtype: str
"""
def id_rem(poly):
"""Vérifie si poly correspond au développement d'une identité
remarquable ou est un carré.
:param poly: polynome à évaluer
:type poly: Polynome
>>> from pyromaths.classes.PolynomesCollege import Polynome
>>> from pyromaths.classes.PolynomesCollege.factoriser import id_rem
>>> id_rem(Polynome('4x^2+12x+9'))
"Polynome('2x')+2*Polynome('2x')*Polynome('3')+Polynome('3')**2"
>>> id_rem(Polynome('-4x^2+12x-9'))
"-(Polynome('2x')-2*Polynome('2x')*Polynome('3')+Polynome('3')**2)"
>>> id_rem(Polynome('4x^2-9'))
"(Polynome('2x')+Polynome('3'))*(Polynome('2x')-Polynome('3'))"
>>> id_rem(Polynome('4x^2'))
"Polynome('2x')**2"
>>> id_rem(Polynome('4x'))
None
:rtype: str ou None
"""
from math import sqrt
from pyromaths.classes.SquareRoot import SquareRoot
poly = poly.ordonne()
if len(poly) == 1:
if poly[0][1] % 2 == 0 and isinstance(poly[0][0], int) and \
Arithmetique.carrerise(poly[0][0]) == 1:
return "%r**2" % (Polynome([[sqrt(abs(poly[0][0])), poly[0][1] // 2]], poly.var, poly.details))
elif len(poly) == 2:
# if isinstance(SquareRoot([1, abs(poly[0][0])]).simplifie(),str):
a = repr(Polynome([[SquareRoot([1, abs(poly[0][0])]), poly[0][1] // 2]], poly.var, poly.details))
b = repr(Polynome([[SquareRoot([1, abs(poly[1][0])]), poly[1][1] // 2]], poly.var, poly.details))
if not poly[0][1] % 2 and not poly[1][1] % 2:
# Les deux exposants sont des carrés
if poly[0][0] * poly[1][0] < 0:
# 3ème identité remarquable
if poly[0][0] < 0: return '%s**2-%s**2' % (b, a)
else: return '%s**2-%s**2' % (a, b)
elif len(poly) == 3:
a = repr(Polynome([[sqrt(abs(poly[0][0])), poly[0][1] // 2]], poly.var, poly.details))
b = repr(Polynome([[sqrt(abs(poly[2][0])), poly[2][1] // 2]], poly.var, poly.details))
if not poly[0][1] % 2 and not poly[2][1] % 2 and (poly[0][1] // 2 + poly[2][1] // 2 == poly[1][1]):
# Ça ressemble à l'une des deux premières indentités remarquables
if poly[0][0] * poly[2][0] > 0 and poly[0][0] * poly[1][0] > 0 and \
4 * poly[0][0] * poly[2][0] == poly[1][0] ** 2:
# 1ère identité remarquable, au signe près
if poly[0][0] > 0:
return a + '**2+2*' + a + '*' + b + '+' + b + '**2'
else:
return '-(' + a + '**2+2*' + a + '*' + b + '+' + b + '**2)'
if poly[0][0] * poly[2][0] > 0 and poly[0][0] * poly[1][0] < 0 and \
4 * poly[0][0] * poly[2][0] == poly[1][0] ** 2:
if poly[0][0] > 0:
return a + '**2-2*' + a + '*' + b + '+' + b + '**2'
else:
return '-(' + a + '**2-2*' + a + '*' + b + '+' + b + '**2)'
return None
def EstFactorise(lcalcul):
"""indique si une liste de calculs est factorisée
:param lcalcul: liste de calculs
:type lcalcul: list
>>> from pyromaths.classes.PolynomesCollege.factoriser import EstFactorise
>>> EstFactorise(["Polynome('3x+4')", "*", "5"])
True
>>> EstFactorise(["Polynome('3x+4')", "*", "5", "+", "Polynome('2x+7')"])
False
:rtype: boolean
"""
# Si le premier symbole est '+' ou '-', alors cela n'influe pas sur somme / produit
dummy = [lcalcul[i] for i in range(len(lcalcul))]
if dummy[0] == '+' or dummy[0] == '-': dummy = dummy[1:]
par = Priorites3.recherche_parentheses(dummy)
if par:
if par[0] == 0 and par[1] == len(dummy):
return EstFactorise(dummy[1:-1])
while par:
del dummy[par[0]:par[1]]
par = Priorites3.recherche_parentheses(dummy)
if '+' in dummy[1:] or '-' in dummy[1:]:
return False
else:
if '+' in dummy or '-' in dummy:
return False
return True
from pyromaths.outils import Arithmetique
lcalcul = Priorites3.splitting(calcul)
if len(lcalcul) == 1:
# On tente une identité remarquable, un facteur commun ou une méthode Lycée (à faire plus tard)
if 'Polynome(' == lcalcul[0][:9]:
poly = eval(lcalcul[0])
id_rem = id_rem(poly)
if id_rem is None and len(poly) > 1:
# Cherchons un facteur commun
facteur = Arithmetique.pgcd([m[0] for m in poly])
exp = min([m[1] for m in poly])
if abs(facteur) != 1 or exp != 0:
k = Polynome([[facteur, exp]], poly.var, poly.details)
a = poly // k
return "*".join([repr(k), repr(a)])
return None
else:
return id_rem
else:
raise ValueError(u'%s n\'est pas un Polynome et ne peut être factorisé')
else:
# C'est soit une somme de polynomes qu'il faut factoriser, soit déjà un produit
if EstFactorise(lcalcul):
# Il faut réduire les sommes
poly = Priorites3.effectue_calcul(lcalcul)
if EstFactorise(poly): return "".join(poly)
else: return None
else:
# On cherche un facteur commun ou une identité remarquable
nbpar = 0
ltermes = [[]]
if lcalcul[0] in '+-':
lsgn = [lcalcul[0]]
else:
lsgn = ['']
if lcalcul[0][:9] == 'Polynome(': ltermes = [[repr(eval(lcalcul[0]))]]
else: ltermes = [[lcalcul[0]]]
for el in lcalcul[1:]:
if el in '+-' and nbpar == 0:
lsgn.append(el)
ltermes.append([])
else:
if el == '(': nbpar += 1
elif el == ')': nbpar += -1
if el[:9] == 'Polynome(': ltermes[-1].append(repr(eval(el)))
else: ltermes[-1].append(el)
if len(ltermes) >= 3 and lcalcul.count('**') > 1 and lcalcul.count('*') > 1 and lcalcul.count('2') > 2:
# On peut être en présence de l'une des 2 premières identités remarquables
exp1 = lcalcul.index('**')
a = lcalcul[exp1 - 1]
indexa = ltermes.index([a, '**', '2'])
sgna = lsgn[indexa] or '+'
exp2 = lcalcul[exp1 + 1:].index('**') + exp1 + 1
b = lcalcul[exp2 - 1]
indexb = ltermes.index([b, '**', '2'])
sgnb = lsgn[indexb] or '+'
for i in range(len(ltermes)):
if len(ltermes[i]) == 5 and ltermes[i].count('2') > 0 and \
ltermes[i].count('*') == 2 and ltermes[i].count(a) and \
ltermes[i].count(b):
indexp = i
sgnp = lsgn[i] or '+'
if sgna == sgnb and sgna != sgnp:
poly = '(%s-%s)**2' % (a, b)
elif sgna == sgnb and sgna == sgnp:
poly = '(%s+%s)**2' % (a, b)
else:
# Pas d'identité remarquable
poly = None
if poly:
if sgna == '-': poly = '-%s' % poly
lindex = [indexa, indexb, indexp]
lindex.sort()
lindex.reverse()
for i in lindex:
lsgn.pop(i)
ltermes.pop(i)
ltermes.insert(min(len(ltermes), indexa, indexb, indexp), Priorites3.splitting(poly))
res = []
for i in range(len(ltermes)):
# TODO: IndexError: list index out of range
if lsgn and lsgn[i]: res.append(lsgn[i])
res.extend(ltermes[i])
return "".join(res)
if (('+' in lsgn or '' in lsgn) and '-' in lsgn) and calcul.count("**") == lcalcul.count("2") == 2 and len(ltermes) == 2:
# 3ème identité remarquable
# print ltermes[0][0], ltermes[1][0]
a, b = eval(ltermes[0][0]), eval(ltermes[1][0])
if lsgn[0] == '-': return '(%r+%r)*(%r-%r)' % (b, a, b, a)
else: return '(%r+%r)*(%r-%r)' % (a, b, a, b)
for k in ltermes[0]:
commun = False
if k[:9] == 'Polynome(':
commun = False
bdetail = False
pos = ltermes[0].index(k)
if len(ltermes[0]) == 1: bdetail = True
elif pos < len(ltermes[0]) - 1 and ltermes[0][pos + 1] == "**": bdetail = True
for i in range(len(ltermes) - 1):
if ltermes[i + 1].count(k):
commun = True
pos = ltermes[i + 1].index(k)
if len(ltermes[i + 1]) == 1: bdetail = True
elif pos < len(ltermes[i + 1]) - 1 and ltermes[i + 1][pos + 1] == "**": bdetail = True
else:
commun = False
break
if commun: break
if commun:
for i in range(len(ltermes)):
pos = ltermes[i].index(k)
if len(ltermes[i]) == 1:
ltermes[i].extend(["*", "1"])
elif pos < len(ltermes[i]) - 1 and ltermes[i][pos + 1] == "**" and ltermes[i][pos + 2] == "2":
ltermes[i][pos + 1:pos + 3] = ["*", ltermes[i][pos]]
elif pos < len(ltermes[i]) - 1 and ltermes[i][pos + 1] == "**":
ltermes[i][pos + 2] == str(eval(ltermes[i][pos + 2]) - 1)
elif not bdetail:
del ltermes[i][pos]
if pos: del ltermes[i][pos - 1]
# supprime le symbole *
else: del ltermes[i][pos]
a = []
for i in range(len(ltermes)):
if lsgn[i]:a.append(lsgn[i])
a.extend(ltermes[i])
if bdetail:
# On affiche le facteur commun de façon claire
return "".join(a)
else:
# On effectuer la factorisation par le facteur commun
return "%s*(%s)" % (k, "".join(a))
else:
bfact = False
for i in range(len(lcalcul)):
if 'Polynome(' == lcalcul[i][:9]:
poly = id_rem(eval(lcalcul[i]))
if poly:
bfact = True
lcalcul[i:i + 1] = Priorites3.splitting(poly)
else:
lcalcul[i] = repr(eval(lcalcul[i]))
if bfact:
return "".join(lcalcul)
else:
return None
def choix_points(min=-4, max=4, nb=5):
"""**choix_points**\ ()
Renvoie un tuple contenant nb coordonnées sous forme de tuple telles que
les abscisses et ordonnées sont distinctes, comprises entre min et max,
une abscisse n'est jamais égale à une ordonnée et la coordonnée (b, a) n'est
pas listée si la coordonnée (a, b) existe.
>>> from pyromaths.ex.troisiemes import notion_de_fonction
>>> notion_de_fonction.choix_points() # doctest: +SKIP
((-4, -2), (-2, 0), (0, 4), (2, -4), (4, 2))
:rtype: tuple
"""
if nb > max - min + 1:
raise ValueError('On demande trop de points vu le min et le max')
abscisse = [i for i in range(min, max + 1)]
for dummy in range(max - min - nb):
del abscisse[randrange(len(abscisse))]
refaire = True
while refaire:
ordonnee = [abscisse[i] for i in range(nb)]
shuffle(ordonnee)
refaire = False
for i in range(nb):
if abscisse[i] == ordonnee[i] or abscisse.index(ordonnee[i]) == ordonnee.index(abscisse[i]):
refaire = True
break
return tuple([(abscisse[i], ordonnee[i]) for i in range(nb)])
def Lagrange(points):
"""**Lagrange**\ (*points*)
Renvoie le polynôme d'interpolation de Lagrange pour les points de coordonnées *points*
Est prévue pour être utilisé avec :py:func:`choix_points`
Associé à :py:func:`pyromaths.outils.Priorites3.priorites`, permet d'obtenir sa version réduite.
Associé à :py:func:`pyromaths.outils.Priorites3.plotify`, permet d'obtenir sa version utilisable avec psplot.
>>> from pyromaths.ex.troisiemes import notion_de_fonction
>>> p = notion_de_fonction.Lagrange(((-4, -2), (-2, 0), (0,4), (2,-4), (4,2)))
>>> from pyromaths.outils import Priorites3
>>> Priorites3.priorites(p)[-1]
['Polynome([[Fraction(5, 48), 4], [Fraction(1, 8), 3], [Fraction(-23, 12), 2], [Fraction(-3, 2), 1], [Fraction(4, 1), 0]], "x", 0)']
>>> Priorites3.plotify(Priorites3.priorites(p)[-1])
5/48*x^4+1/8*x^3-23/12*x^2-3/2*x^1+4/1
"""
PIL = []
for i in range(len(points)):
if points[i][1]:
PIL.append('Fraction(%s, ' % points[i][1])
produit = []
for j in range(len(points)):
if j != i: produit.append(repr(points[i][0] - points[j][0]))
produit = repr(eval("*".join(produit)))
PIL[i] += produit + ")*"
produit = []
for j in range(len(points)):
if j != i and points[j][0] > 0: produit.append("Polynome(\"x-%s\", details = 0)" % points[j][0])
elif j != i and points[j][0] < 0: produit.append("Polynome(\"x+%s\", details = 0)" % -points[j][0])
elif j != i and points[j][0] == 0: produit.append("Polynome(\"x\", details = 0)")
produit = "*".join(produit)
PIL[i] += produit
else:
PIL.append('0')
return "+".join(PIL)