Skip to content

Instantly share code, notes, and snippets.

@lovasoa
Created February 3, 2012 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lovasoa/1732967 to your computer and use it in GitHub Desktop.
Save lovasoa/1732967 to your computer and use it in GitHub Desktop.
polygnome
  1. Polygnome a été codé par Ulysse Lojkine en 2010 pour le projet ALEV (Algorithmie et Logique dans les Espaces Virtuels) du lycée Henri IV.

  2. Polygnome est placé sous licence libre GNU-GPL par son programmeur.

  3. Quelques infos d'utilisation... 3.1. Pour entrer un nouveau polynôme... 3.1.1. Séparez les monômes par le signe +. 3.1.2. Utilisez le signe - et le signe + pour entrer des coefficients négatifs. 3.1.3. Séparez le numérateur et le dénominateur par le signe / si vous voulez utiliser des coefficients rationnels. 3.1.4. N'utilisez pas d'espace. 3.1.5. Exemple : "7x8+x5+5/3x+-8" 3.2. Pour entrer une formule... 3.2.1. Pour nommer un polynôme, utilisez la lettre f suivie de son numéro dans la liste. 3.2.2. Utilisez les opérateurs arithmétiques usuels... 3.2.2.1. Le + pour l'addition. 3.2.2.2. Le - pour la soustraction. 3.2.2.3. Le * pour la multiplication. 3.2.2.4. Le ** pour la puissance. 3.2.2.5. Le / pour la division (factorisation). 3.2.2.6. Les parenthèses () pour isoler une expression. 3.2.3. À l'exception de l'opérateur & utilisé à la place du rond pour la composition. 3.2.4. Exemple : "(f0+f2)**7 - f1"

  4. Si vous cherchez un programme complet, ne négligez pas Polynomial. 4.1. Polynomial est disponible... 4.1.1. fichiers par RubyGem 4.1.2. source en ligne à https://github.com/adrianomitre/Polynomial/tree/gh-pages 4.2. Fonctionnalités supplémentaires... 4.2.1. Coefficients complexes. 4.2.2. Meilleure gestion des erreurs. 4.2.3. Peut-être d'autres choses. 4.3. Inconvénients... 4.3.1. Ce n'est pas moi qui l'ai fait. 4.3.2. Tous les coefficients même nuls sont enregistrés. 4.3.3. Source en anglais.

# Classe principale
# Retourne 0 si nil, nombre sinon
def obj2nbr(obj)
return (obj == nil) ? 0 : obj
end
class Polynome
require 'rational'
require 'complex'
# Toutes les variables de classe sont lisibles depuis l'extérieur
attr_reader :str, :liste, :derivee, :deg
# Fonction d'initialisation (appelée par Polynome.new(str))
def initialize(poly=0) #Par défaut, on crée le polynôme nul
if poly.is_a? Hash : @liste = poly # expression du polynôme sous forme de liste ; ex. : {0 => 1, 1 => 1, 3 => 4}
elsif poly.is_a? Numeric : @liste = {0 => poly}
elsif poly.is_a? String : @liste = fromString(poly).liste
else raise "L'argument doit être un hash, une constante, ou une chaîne de caractères. Vous avez fourni '"+poly.inspect+ "'."
end
@liste.default = 0 #Tous les monômes qui n'ont pas été définis ont un coefficient nul
@liste.delete_if {|k, v| v==0} # on supprime tous les monômes nuls
@deg = liste.empty? ? -(1.0/0) : @liste.keys.max # degré du polynôme ; ex. : 4. Le degré du polynôme nul est moins l'infini
end
# Passage de la chaîne à la liste, en moins bien, par Ophir
def fromString(str)
str = str.downcase.tr(" ","")
polyFinal = Polynome.new({0=>0}) # Le polynôme nul
polyActuel = Polynome.new({0=>1}) # 1
i=0
while i < str.length
case str [i..i]
when "(" :
newPos = str[i+1..-1].index(")") + i+1;
polyParentheses = fromString(str[ i+1 .. newPos-1])
i=newPos+1 #newPos + 1: le caractère après la parenthèse fermante
if str[i .. i] == "^":
newPos = str[i+1 .. -1].index(/[^0-9]|$/)+i+1;
polyActuel *= polyParentheses ** (str[i+1 .. newPos-1].to_i)
i=newPos
else
polyActuel *= polyParentheses
end
when "+":
polyFinal += polyActuel
polyActuel = Polynome.new(1) # P(X) = 1
i+=1
when "-":
polyFinal += polyActuel
polyActuel = Polynome.new(-1) # P(X) = -1
i+=1
when "x":
if str[i+1 .. i+1] == "^":
newPos = str[i+2 .. -1].index(/[^0-9]|$/)+i+2;
puissance = str[i+2 .. newPos-1].to_i #i+1 parce que le caractère ^ est en position i+1
i=newPos
else
puissance = 1
i=i+1
end
polyActuel *= Polynome.new({puissance => 1})# P(X) = X^puissance
when "0".."9", "i":
newPos = str[i..-1].index(/[^0-9]|$/)+i;
coeff = (i==newPos) ? 1 : str[i .. newPos-1].to_f
coeff = Integer(coeff) if coeff == Integer(coeff)
if str[newPos .. newPos] == "i" #Complexe
coeff = Complex(0,coeff)
newPos+=1
end
polyActuel *= coeff #Polynôme constant égal à coeff
i=newPos
else #Valeur non reconnue
i+=1
end
end
return (polyActuel+polyFinal)
end
# Dérivation du polynôme
def deriver(ordre=1)
if ordre == 1
retour = {} # on crée un hash vide (retour une fois rempli)
# La dérivée d'un monôme de degré non nul est de degré deg-1 et de coefficient coeff*deg
@liste.each {|deg, coeff| retour [deg -1] = coeff*deg if deg > 0}
return Polynome.new(retour)
else
return self.deriver(ordre-1).deriver()
end
end
# Intégration du polynôme
def integrer(ordre=1)
if ordre == 1
retour = {} # on crée un hash vide (retour une fois rempli)
# La dérivée d'un monôme de degré non nul est de degré deg-1 et de coefficient coeff*deg
@liste.each {|deg, coeff| retour[deg +1] = Rational(coeff,deg+1)}
return Polynome.new(retour)
else
return self.integrer(ordre-1).integrer()
end
end
def racines
a,b,c = liste[2], liste[1], liste[0]
if deg==2
delta = b**2 - 4*a*c
return [(-b-Math.sqrt(delta))/(2*a)] if delta==0
return [(-b-Math.sqrt(delta))/(2*a), (-b+Math.sqrt(delta))/(2*a)]
elsif deg==1
return [Rational(c,-b)]
else
raise "Impossible de trouver les racines."
end
end
# Somme de polynômes
def +(poly2)
return self+Polynome.new(poly2) if poly2.is_a? Numeric
retour = poly2.liste.clone
@liste.each { |k, v| retour[k] += v} #On additonne tous les monomes de @liste 1 par 1
return Polynome.new(retour)
end
def -@
self*(-1)
end
# Différence de polynômes
def -(poly2)
return self + (-poly2) # a + b = a + (-1)b
end
# Produit de polynômes
def *(poly2)
return self*Polynome.new(poly2) if !poly2.is_a? Polynome
retour = {}
retour.default=0
self.liste.each{ |k1, v1| poly2.liste.each{ |k2, v2|
retour[k2+k1] += v1*v2
}}
return Polynome.new(retour) # on retourne le polynôme créé à partir du hash
end
# Puissance d'un polynôme
def **(n)
if n<0
raise "Impossible d'avoir une puissance négative."
end
# f^n = f*f^(n-1) = ... = f*f*f*...*f
return (n == 0) ? Polynome.new(1) : self * self ** (n - 1)
end
alias ^ **
def division (dividende, diviseur) #Factorisation
return [self*Rational(1,diviseur), 0] if diviseur.is_a? Numeric
raise "Division par zéro !" if diviseur.liste.empty? # On ne peut pas diviser par le polynôme nul
# Le dividende est le polynôme depuis lequel la fonction est appelée
# Le diviseur est l'argument
# Le résultat est au départ le polynôme nul
quotient, reste = Polynome.new(0), dividende.clone
# Jusqu'à ce qu'il n'y ait plus rien à diviser, on applique l'algorithme de division polynômiale
while reste.deg >= diviseur.deg
monome = Polynome.new({
(reste.deg-diviseur.deg) => #Degré du monôme
Rational(reste.liste[reste.deg], diviseur.liste[diviseur.deg]) }) #Coefficient du monôme
quotient += monome
reste -= monome * diviseur
end
return [quotient, reste]
end
def /(diviseur)
return division(self, diviseur)[0]
end
def %(diviseur)
return division(self, diviseur)[1]
end
# Composition
def & (poly2)
retour = Polynome.new(0)
@liste.each {|deg, coeff| retour += coeff * poly2 ** deg}
return retour
end
# Affichage
def to_s
return "0" if is_null?
retour = "" # on crée une chaîne vide qui, une fois remplie, sera retournée
# Pour chaque monôme on ajoute à la chaîne le coeff, la variable, le deg, le symbole +
@liste.keys.sort.reverse.each {|deg|
retour += ((@liste[deg] < 0) ? " - " : " + ") if deg != @deg or @liste[deg] == -@liste[deg].real.abs
if (@liste[deg]!=1 && @liste[deg]!=-1) || deg == 0
if @liste[deg].real == @liste[deg] #Si le coefficient est réel
retour += @liste[deg].abs.to_s
else #Si le coefficient est complexe
retour += format("(%s)", @liste[deg].to_s)
end
end
if deg != 0
retour += "X"
if deg != 1
retour += "^"+deg.to_s
end
end
}
return retour.strip
end
alias inspect to_s
def coerce(x)#Permet de rendre les opérations commutatives, donc d'avoir 3*Poly
[self, x]
end
def is_null?
@liste=={}
end
end
X = Polynome.new({1=>1})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment