Calculos matemáticos simples

Boa Noite,

Estou criando algumas classes com calculos matematicos para criar um aplicativo para android. Coisa simples apenas para iniciar na plataforma.

Acham que o código abaixo está muito “gambiarra”?

package com.incosd.mathpack;

@SuppressWarnings("unused")
public class Geometria {
	private double catOp;
	private double catAdj;
	private double seno;
	private double cos;
	private double tan;

	public double getCatOp() {
		return catOp;
	}

	public void setCatOp(double catOp) {
		this.catOp = catOp;
	}

	public double getCatAdj() {
		return catAdj;
	}

	public void setCatAdj(double catAdj) {
		this.catAdj = catAdj;
	}

	public void setSeno(double seno) {
		this.seno = seno;
	}

	public void setCos(double cos) {
		this.cos = cos;
	}

	public void setTan(double tan) {
		this.tan = tan;
	}


	public double hipotenusa (double catOp, double catAdj){
		this.catOp =catOp;
		this.catAdj =catAdj;
		double quadHip = Math.pow(catOp, 2)+ Math.pow(catAdj, 2);
		return Math.sqrt(quadHip);
	}


	public double calcSeno(int angulo, double catetoOp, double hipotenusa){
		switch (angulo) {
		case 30:
			seno = 0.5;
			break;
		case 45:
			seno = Math.sqrt(2)/2;
			break;
		case 60:
			seno = Math.sqrt(3)/2;
			break;
		default:
			new RuntimeException("Angulo diferente de 30 , 45 ou 60");
			break;
		}
		return (seno*hipotenusa)/catetoOp;
		
	}

}

Coloquei apenas um metodo para pedir ajuda de vocês e assim ir melhorando antes de fazer tudo. Eu retirei os os getters que aparentemente eu não vou usar (lendo um post no blog da caelum).
Como eu vou usar o mesmo esquema para calcular seno, cos e tangente, seria melhor isolar para reaproveitar o código?
Para criar os métodos estou usando uma ideia básica:

Quero desenvolver o aplicativo respeitando bem OO e assim que eu aprender, se possivel, aplicar conceitos de teste e design patterns. Sendo assim, podem criticar que não vou ficar de mimimi rsrs

[ ]'s

Uma coisa que eu notei é que você tem atributos na sua classe, porém seus métodos não dependem deles. Seus métodos dependem apenas dos argumentos informados, então não precisaria ter atributos de classe.

E outra coisa, se não me engano a classe Math já tem métodos pra esses cálculos, me corrijam se eu estiver errado.

Rodrigo,

Esses atributos eu criei para usar com outros metodos…Essa classe seria para calculos usando geometria, eu não cheguei a montar a classe toda para avaliar, com ajuda dos colegas, se essa linha de raciocinio poderia ser mais “clean” ou está OK…

Dei uma olhada rápida na classe Math e realmente tem bastante coisas que eu não sabia… vai facilitar ainda mais. Obrigado!

[ ]'s

[quote=Ubb3r]Boa Noite,

Estou criando algumas classes com calculos matematicos para criar um aplicativo para android. Coisa simples apenas para iniciar na plataforma.

Acham que o código abaixo está muito “gambiarra”?

[/quote]

Não muito, só um pouco. É que não está orientado a objetos.

Por exemplo um angulo vc implementou como inteiro e em graus. mas e se eu quiser passar trinta graus e meio ? Existe isso ? Existe. Mas sua classe não permite calcular usando 30,5 graus.
Então a primeira regra a ser seguida que vc esqueceu é : use o tipo correto. Então vc deveria, no minimo, usar double e não int.
Ah! mas ai tem o problema de saber se o double representa graus ou radianos … então deveriamos criar uma classe Angulo que tem o valor e a unidade do angulo. Assim os métodos podem usar o valor na unidade certa e converter se necessário. A class math aceita valores em radianos, por exemplo.

Depois tem o problema dos atributos. Sua desculpa de que será usado para outra coisa não convence pelo simples facto que uma classe não pode fazer mais que uma coisa. Se existe “outra coisa” está errado. Não OO.
Se a classe geometria serve para fazer contas então é isso que ela deve fazer e pronto. Se ela faz isso sobre valores que recebe como parametro, então não ha porque ter atributos na classe e os métodos devem ser estáticos.

Agora, entenda que se eu tenho a classe angulo, eu posso escerver isto


Angulo angulo = Angulo.valueOf(30, Angulo.Unidade.Grau);

double seno = Geometria.seno(angulo)

// ou 

double seno = angulo.seno();

Se usar a segunda forma, não preciso q a classe Geometria tenha uma operação seno.

Vai dar o mesmo resultado ? Vai. Mas a orientação a objetos é melhor. Meu conceito fundamental nesse código é Angulo, então eu devo ter uma classe que o representa e todos os métodos relacionados a “angulo” devem estar nessa classe.

O mesmo conceito poderia ser usado para os catetos, ou ir mais longe e construir uma classe Triangulo que dados dois lados e seu angulo, calcula o outro lado e os outros angulos, etc… Afinal, esse é o problema que vc está tentando resolver. Hipotesusas só existem em triangulos retangulos , portanto seu classe Geometria não é tão generica como parece, mas se vc construir uma classe triangulo, ai sim, fará sentido. E a classe triangulo não será uma classe utilitária que faz contas, será um objeto que realmente tem propriedades. Vc pode começar criando a classe TrianguloRetangulo e depois abstrair para o Triangulo em geral.

Sergio,

Primeiro muito obrigado! é essa ajuda que eu realmente precisava… Para a classe angulo eu posso implementar essa relação?:

Eu vou explorar um pouco mais as classes prontas com tratamento para matemática… Vou deixar nessa classe geometria apenas os métodos que uso e os valores para os métodos eu mantenho apenas os valores de entrada.
Os métodos que são bem parecidos, seria bom eu criar uma interface e sobrescrevê-los ?

Off: hesitei um pouco na hora de escolher uns cursos na Caelum, mas acho que foi bom escolher o de OO kkkk’ preciso melhorar bastante.

[ ]'s

Nossa Senhora, por que é que vai botar uma tabela de senos, cosenos e tangentes dentro do seu código, em vez de usar Math.sin, Math.cos e Math.tan ? (OK. eles calculam em radianos, mas há também um método em java.lang.Math que converte de graus para radianos :slight_smile:

De qualquer forma, você pode até usar uma tabela (apenas para treinar) e também implementar a interpolação em tabelas (por exemplo, quanto é o seno de 1,5 grau? )

[quote=entanglement]Nossa Senhora, por que é que vai botar uma tabela de senos, cosenos e tangentes dentro do seu código, em vez de usar Math.sin, Math.cos e Math.tan ? (OK. eles calculam em radianos, mas há também um método em java.lang.Math que converte de graus para radianos :slight_smile:

De qualquer forma, você pode até usar uma tabela (apenas para treinar) e também implementar a interpolação em tabelas (por exemplo, quanto é o seno de 1,5 grau? )[/quote]

Por enquanto é treino mesmo, porque ainda não conheço bem a classe Math. Já peguei a Doc. para ler… estou usando o que tenho disponível agora e conforme as dicas e ajudas eu vou corrigindo e otimizando.

[ ]'s

Só mais um probleminha. Na verdade, como você deve saber, seno de um grau é algo como 0,01745240643728351281941897851632… , não 0,0175 (que é um valor que está correto só até a quarca casa).

Então, se vai executar teste unitário para o cálculo de seno, deve entender que o valor calculado não é exatamente igual, e sim apenas os quatro primeiros dígitos depois da vírgula é que devem bater. Você precisa, no seu teste unitário, de criar um método que verifica se os números são próximos até a quarta casa (por exemplo). Um exemplo de um método desses:

public static boolean isAlmostEqual (double x, double y) {
     return Math.abs (x - y) < 0.00005;
}

No seu caso, isAlmostEqual (Math.sin (Math.toRadians (1.0)), 0.0175)) deve retornar true, já que está correto até a quarta casa depois da vírgula.

(Lição de casa - por que é que usei 0.00005 em vez de 0.0001 ? )

[quote=entanglement]Só mais um probleminha. Na verdade, como você deve saber, seno de um grau é algo como 0,01745240643728351281941897851632… , não 0,0175 (que é um valor que está correto só até a quarca casa).

Então, se vai executar teste unitário para o cálculo de seno, deve entender que o valor calculado não é exatamente igual, e sim apenas os quatro primeiros dígitos depois da vírgula é que devem bater. Você precisa, no seu teste unitário, de criar um método que verifica se os números são próximos até a quarta casa (por exemplo). Um exemplo de um método desses:

public static boolean isAlmostEqual (double x, double y) {
     return Math.abs (x - y) < 0.00005;
}

No seu caso, isAlmostEqual (Math.sin (Math.toRadians (1.0)), 0.0175)) deve retornar true, já que está correto até a quarta casa depois da vírgula.

(Lição de casa - por que é que usei 0.00005 em vez de 0.0001 ? )
[/quote]

Boa questão… Vou tentar montar essa ideia e corrigir os outros pontos. Em relaçãoa “lição de casa”:

“0,01745240643728351281941897851632… , não 0,0175”:

0,01745 - 0,0175 = 0,00005

[ ]'s