Created
November 30, 2011 02:00
-
-
Save danicuki/1407633 to your computer and use it in GitHub Desktop.
Polinomio implementation in Scala (http://www.ime.usp.br/~reverbel/PFC-11/trabalhos/ep3/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pfc | |
private case class Term(coef: Double, exp: Int) { | |
require(coef != 0 && exp >= 0) | |
} | |
object Pol { | |
// conversao implicita de Double em Pol | |
implicit def doubleToPol(d: Double): Pol = Pol(d, 0) | |
// metodos de fabrica acessiveis para os clientes | |
def apply(coef: Double, exp: Int): Pol = { | |
if (coef == 0) new Pol(Nil) | |
else new Pol(new Term(coef, exp) :: Nil) | |
} | |
def apply(coef: Double): Pol = Pol(coef, 0) | |
// metodo de fabrica interno (serve apenas para evitar o uso de new) | |
private def apply(terms: List[Term]): Pol = new Pol(terms) | |
// metodo auxiliar para as operacoes de adicao e subtracao de polinomios | |
private def add(terms1: List[Term], terms2: List[Term]): List[Term] = { | |
if (terms1 == Nil) return terms2 | |
if (terms2 == Nil) return terms1 | |
if (terms1.head.exp > terms2.head.exp) return terms1.head :: add(terms1.tail, terms2) | |
if (terms1.head.exp < terms2.head.exp) return terms2.head :: add(terms1, terms2.tail) | |
else if (terms2.head.coef + terms1.head.coef != 0) | |
return Term(terms2.head.coef + terms1.head.coef, terms1.head.exp) :: add(terms1.tail, terms2.tail) | |
else | |
return add(terms1.tail, terms2.tail) | |
} | |
} | |
class Pol private (private val terms: List[Term]) { | |
// construtor auxiliar | |
// (n.b.: tanto o construtor primario como o auxiliar sao privados) | |
// private def this(coef: Double, exp: Int) | |
// aritmetica de polinomios | |
def +(that: Pol): Pol = Pol(Pol.add(this.terms, that.terms)) | |
def -(that: Pol): Pol = this + (-that) | |
def *(that: Pol): Pol = { | |
terms.map(t => that * t).foldLeft(Pol(0))((acum, item) => acum + item) | |
} | |
def /(that: Pol): Tuple2[Pol, Pol] = { | |
if (that.degree > this.degree) return (Pol(0), this) | |
val partial = Pol(terms.first.coef / that.terms.first.coef, terms.first.exp - that.terms.first.exp) | |
val nextDividendo = this - (partial * that) | |
if (nextDividendo == Pol(0)) return (partial, Pol(0)) | |
val nextDivide = (nextDividendo / that) | |
return (partial + nextDivide._1, nextDivide._2) | |
} | |
// operadores unarios | |
def unary_+ : Pol = this | |
def unary_- : Pol = Pol(terms.map(t => Term(-t.coef, t.exp))) | |
// aritmetica mista (o operando 1 e' um polinomio, o operando 2 e' um numero) | |
def +(d: Double): Pol = this + Pol(d) | |
def -(d: Double): Pol = this - Pol(d) | |
def *(d: Double): Pol = this * Pol(d) | |
def /(d: Double): Pol = (this / Pol(d))._1 | |
// grau, potenciacao e derivacao | |
def degree: Int = terms.head.exp | |
def ^(n: Int): Pol = if (n == 0) Pol(1) else this * (this ^ (n - 1)) | |
def deriv: Pol = { | |
terms.foldLeft(Pol(0))((acum, t) => acum + Pol(t.coef * t.exp, if (t.exp == 0) 0 else t.exp - 1)) | |
} | |
def ! : Pol = deriv | |
// calcula o valor do polinomio alvo para um dado valor de x | |
def apply(x: Double): Double = { | |
terms./:(0.0) { | |
(acum, t) => acum + t.coef * BigDecimal.valueOf(x).pow(t.exp).toDouble | |
} | |
} | |
// composicao do polinomio alvo com outro polinomio | |
def apply(that: Pol): Pol = { | |
terms./:(Pol(0)) { | |
(acum, term) => acum + Pol(term.coef) * (that ^ term.exp) | |
} | |
} | |
// sobrescrita de metodos da classe Any | |
override def equals(other: Any): Boolean = (toString == other.toString) | |
// override def hashCode: Int | |
override def toString: String = | |
if (terms.isEmpty) "0" else terms.foldLeft("")((acum, term) => calcString(term, acum)) | |
private def calcString(term: Term, acum: String): String = { | |
val sinal = if (term.coef < 0) "-" else "+" | |
val df = new java.text.DecimalFormat("#.################") | |
val valor = if (term.coef.abs == 1 && term.exp > 0) "" else df.format(term.coef.abs) | |
val letra = if (term.exp > 0) "x" else "" | |
val expo = if (term.exp >= 2) "^" + term.exp else "" | |
val pref = | |
if (acum == "") | |
if (sinal == "+") "" else "-" | |
else | |
" " + sinal + " " | |
(acum + pref + valor + letra + expo).trim() | |
} | |
// metodo auxiliar que multiplica o polinomio alvo por um termo simples | |
private def *(term: Term): Pol = { | |
Pol(terms.map(item => Term(term.coef * item.coef, term.exp + item.exp))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment