# -*- coding: utf-8 -*- from ..outils.decimaux import decimaux from ..outils.Arithmetique import carrerise, pgcd, ppcm from math import sqrt from Fractions import Fractions def produitfacteurs(facteurs): """Affiche sous forme de produit les éléments d'une liste.""" prodfacteurs = '' for element in facteurs: prodfacteurs += str(element) + _(' \\times ') return prodfacteurs[:-7] class Racine: def __init__(self, radicande, coeff = 1, indice = 2): if (radicande < 0) or not (isinstance(indice, int)): print(_(u"Erreur de définition ! Le radicande doit être positif et l'indice un nombre entier !")) self.radicande = radicande self.indice = indice # Nombre entier self.coeff = coeff # Coeff devant la racine def __add__(self, other): if not (isinstance(other, Racine)): return str(self) + " + " + str(other) if (self.radicande == other.radicande) and (self.indice == other.indice): return [str(self.simplifie()[0]) + "+" + str(other.simplifie()[0]), Racine(self.radicande, self.coeff + other.coeff, self.indice)] else: return str(self) + " + " + str(other) def __radd__(self, other): return self + other def __sub__(self, other): if not (isinstance(other, Racine)): return str(self) + " + " + str(other) if (self.radicande == other.radicande) and (self.indice == other.indice): return Racine(self.radicande, self.coeff - other.coeff, self.indice) else: return (str(self) + " - " + str(other), "tset") def __rsub__(self, other): return -(self - other) def __mul__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, self.coeff * other, self.indice) elif self.indice == other.indice: return Racine(self.radicande * other.radicande, self.coeff * other.coeff, self.indice) else: return str(self) + ' x ' + str(other) def __rmul__(self, other): return self * other def __div__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, self.coeff / other, self.indice) elif self.indice == other.indice: return Racine(self.radicande / float(other.radicande), self.coeff / float(other.coeff), self.indice) else: return str(self) + ' / ' + str(other) def __rdiv__(self, other): if (isinstance(other, float)) or (isinstance(other, int)): return Racine(self.radicande, other / float(self.coeff * self.radicande), self.indice) elif self.indice == other.indice: return Racine(other.radicande / float(self.radicande), other.coeff / float(self.coeff), self.indice) else: return str(other) + ' / ' + str(self) def __str__(self): if self.coeff == 0: return "0" else: if self.coeff == 1: coeff = "" else: coeff = decimaux(self.coeff, 1) + " \\, " if self.radicande == 0: coeff = "" racine = "" radicande = "0" elif self.indice == 2: racine = "\\sqrt{" radicande = decimaux(self.radicande, 1) + "}" else: racine = "\\sqrt[{0}]{{".format(self.indice) radicande = decimaux(self.radicande, 1) + "}" return coeff + racine + radicande def simplifie(self): facteurs = factor(self.radicande) prodfacteurs = produitfacteurs(facteurs) if self.indice == 2: racine = "\\sqrt{" else: racine = "\\sqrt[{0}]{{".format(self.indice) coeff = self.coeff radicande = self.radicande detail = [str(self), ' = ', str(coeff) + racine + prodfacteurs + '}'] for element in facteurs: if facteurs.count(element) % self.indice == 0: coeff *= element for n in range(self.indice): facteurs.remove(element) radicande = radicande // (element**(self.indice)) prodfacteurs = produitfacteurs(facteurs) detail.append(' = ') detail.append(str(coeff) + _(' \\times ') + racine + prodfacteurs + '}') if radicande == 1: return (coeff, detail) else: return (Racine(radicande, coeff, self.indice), detail) def simplifie_racine(n): '''renvoie coeff,radicande où sqrt(n)=coeff*sqrt(radicande)''' if n==0: return 0,0 else: ncar=carrerise(n) return int(sqrt(n//ncar)),ncar def pTeX(n): """renvoie (n) si n<0""" if n<0: return "("+decimaux(n)+")" else: return decimaux(n) def tTeX(n): if n==1: return "" elif n==-1: return "-" elif n>=0: return "+"+decimaux(n) else: return decimaux(n) class RacineDegre2: def __init__(self,numerateur=0,denominateur=1,coeff=1,radicande=0): self.numerateur=numerateur self.denominateur=denominateur self.coeff=coeff self.radicande=radicande def __str__(self): if isinstance(self.numerateur,str) or isinstance(self.numerateur,unicode): #utilisé dans le détail de la simplification numerateur=self.numerateur else: numerateur=decimaux(self.numerateur)*(self.numerateur!=0) #renvoie "" si self.numerateur=0 if self.radicande!=0: if isinstance(self.coeff,str) or isinstance(self.coeff,unicode):#utilisé dans le détail de la simplification if self.coeff[0]!="-" and self.coeff[0]!="+": numerateur+="+" numerateur+=self.coeff+"\\sqrt{"+decimaux(self.radicande)+"}" elif self.coeff==1: numerateur+="+\\sqrt{"+decimaux(self.radicande)+"}" elif self.coeff==-1: numerateur+="-\\sqrt{"+decimaux(self.radicande)+"}" else: numerateur+=tTeX(self.coeff)+"\\sqrt{"+decimaux(self.radicande)+"}" if numerateur=='': numerateur = '0' if self.denominateur==1: result=numerateur else: result="\\dfrac{%s}{%s}"%(numerateur,self.denominateur) if result[0]=='+': return result[1:] else: return result def simplifie(self,detail=False): liste_detail=[] coeff,radicande=simplifie_racine(self.radicande) numerateur=self.numerateur if self.radicande!=0: if self.coeff==1: det_coeff="+ " elif self.coeff==-1: det_coeff="- " else: det_coeff=(_("%s\\times "))%(self.coeff) if coeff!=1 or radicande==1: det_coeff+=str(coeff) else: det_coeff="0" if radicande==1: #det_coeff=_("%s\\times%s")%(tTeX(self.coeff),coeff) liste_detail.append("\\dfrac{%s %s}{%s}"%\ (self.numerateur,det_coeff ,self.denominateur)) radicande=0 numerateur=self.numerateur+(self.coeff)*int(coeff) coeff=0 if coeff!=1: liste_detail.append(str(RacineDegre2(numerateur, self.denominateur, det_coeff, radicande))) coeff=(self.coeff)*int(coeff) simplifie=pgcd(pgcd(coeff,numerateur),self.denominateur) numerateur=numerateur//simplifie coeff=coeff//simplifie denominateur=self.denominateur//simplifie if simplifie!=1: if radicande!=0 or denominateur!=1: det_numerateur=_("%s_{\\times %s}")%(numerateur,pTeX(simplifie)) det_denominateur=_("%s_{\\times %s}")%(denominateur,pTeX(simplifie)) det_coeff=_("%s_{\\times %s}")%(coeff,pTeX(simplifie)) liste_detail.append(str(RacineDegre2(det_numerateur,det_denominateur,det_coeff,radicande))) liste_detail.append(str(RacineDegre2(numerateur,denominateur,coeff,radicande))) if detail: return RacineDegre2(numerateur,denominateur,coeff,radicande),liste_detail return RacineDegre2(numerateur,denominateur,coeff,radicande) def __add__(self,other): if isinstance(other,RacineDegre2): if self.radicande==other.radicande or self.radicande==0 or other.radicande==0: radicande=max(self.radicande,other.radicande) premier,second=self,other else: premier=self.simplifie() second=other.simplifie() if self.radicande==other.radicande or self.radicande==0 or other.radicande==0: radicande=max(self.radicande,other.radicande) else: return NotImplemented denominateur=ppcm(premier.denominateur,second.denominateur) facteur1=denominateur/premier.denominateur facteur2=denominateur/second.denominateur #if self.radicande==other.radicande: coeff=premier.coeff*facteur1*(premier.radicande!=0)+second.coeff*facteur2*(second.radicande!=0) if coeff==0: radicande=0 return RacineDegre2(premier.numerateur*facteur1+second.numerateur*facteur2, denominateur, coeff, radicande) elif isinstance(other,int): return self + RacineDegre2(other) elif isinstance(other,Fractions): return self + RacineDegre2(other.numerateur,other.denominateur) def __radd__(self,other): return self+other def __neg__(self): return RacineDegre2(-self.numerateur,self.denominateur,-self.coeff,self.radicande) def __sub__(self,other): return self+(-other) def __rsub__(self,other): return -self + other def __mul__(self,other): if isinstance(other,Fractions): return self*RacineDegre2(other.numerateur,other.denominateur,0,self.radicande) elif isinstance(other,int): return self*RacineDegre2(other,1,0,self.radicande) else: radicande=max(self.radicande,other.radicande)#cela autorise d'avoir un radicande=0 mais n'efface pas l'autre coeff=self.numerateur*(other.coeff*(other.radicande!=0))+(self.coeff*(self.radicande!=0))*other.numerateur if coeff==0: radicande=0 numerateur=self.numerateur*other.numerateur+(self.coeff*other.coeff)*(not(self.radicande==0 or other.radicande==0))*self.radicande return RacineDegre2(numerateur, self.denominateur*other.denominateur, coeff, radicande) def __invert__(self): return self.denominateur*RacineDegre2(self.numerateur,self.numerateur**2-self.coeff**2*self.radicande,-self.coeff,self.radicande) def __div__(self,othrer): return self*~other def __rdiv__(self,other): return ~self*other def __rmul__(self,other): return self*other def __pow__(self,n): result=1 for i in range(n): result=result*self return result def __float__(self): return (self.numerateur+self.coeff*sqrt(self.radicande))/self.denominateur def __cmp__(self,other): comp=float(self)-float(other) if comp>0: return 1 elif comp<0: return -1 else: return 0