Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

josielold

Fazer melhoras nesse código

Recommended Posts

Olá pessoal.

Tenho um código aqui bastante antigo, guardei para usar, caso precisasse algum dia.

Cehgou o dia em que eu precisei desse código, por uma causa muito nobre, breve todos saberão :) e eu preciso mehorá-lo, pois ele é meio feinho...

É um código que gera cálculos matemáticos aleatoriamente. ~Vocês poderiam dar-me um help por favor? agradecido desde já.

Código:

$operators=array('+', '-', '*', '/');
$a=mt_rand(0, 10);
$operator=$operators[array_rand($operators)];
$b=mt_rand(0, 10);
eval("\$result=$a$operator $b;");

 

Valeu!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Existem duas coisas que podem ser melhoradas.

 

A primeira é cuidar para que você não receba um "Division by zero". A segunda é fazer o eval funcionar, já que da forma como está, não funciona, nem mesmo se colocar um print antes da função.

 

Para rrumarisso, veja como eval() funciona.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Um padrão muito legal para esse fim é o Interpreter:

 

Interpreter :seta: Comportamental

 

Motivação:

O padrão Interpreter descreve como definir uma gramática simples, representando as sentenças dessa gramática e interpretando essas sentenças.

Estrutura:

gallery_94216_23_2564.png

 

Participantes:

AbstractExpression
:

Define a operação abstrata interpret que é comum para todos os nós da árvore abstrata.

 

TerminalExpression
:

Implementa a operação interpret associada com os símbolos terminais da árvore.

 

NonterminalExpression
:

Implementa a operação interpret associada com os símbolos não terminais da árvore.

Mantém instâncias para cada um dos símbolos relacionados com a operação.

 

Context
:

Mantém informações que são globais para todo o Interpreter.

 

Client
:

Constroi (ou recebe) a árvore abstrata que representa a sintaxe da gramática, que é construída utilizando os nós terminais e não terminais.

Chama a operação interpret.

 

O padrão Interpret não define um parser, apenas como representar os nós da árvore. Como o problema também não envolve a análise de expressão, uma implementação simples de Interpreter resolve muito bem, vejamos:

 

AbstractExpression.php

<?php
/**
* Define a operação abstrata interpret que é comum para todos os nós da árvore abstrata.
*/
abstract class AbstractExpression {
public abstract function interpret( Context $context );
}

 

Context.php

<?php
/**
* Mantém informações que são globais para todo o Interpreter.
*/
class Context {
}

 

Nesse caso, o Context não é utilizado, precisaríamos dele caso estivéssemos trabalhando com expressões mais complexas, variáveis, loops, etc...

 

Agora, uma expressão terminal:

 

NumericExpression.php

<?php
/**
* Implementa a operação interpret associada com os símbolos terminais da árvore.
*/
class NumericExpression extends AbstractExpression {
/**
 * @var	float
 */
private $value;

public function __construct( $value ) {
	$this->value = (float) $value;
}

/**
 * @param	Context $context
 * @see		AbstractExpression::interpret()
 */
public function interpret( Context $context ) {
	return $this->value;
}
}

 

E algumas expressões não terminais, primeiro a definição dela:

 

BinaryOperationExpression.php

<?php
/**
* Mantém instâncias para cada um dos símbolos relacionados com a operação.
*/
abstract class BinaryOperationExpression extends AbstractExpression {
/**
 * @var	AbstractExpression
 */
protected $a;

/**
 * @var	AbstractExpression
 */
protected $b;

final public function __construct( AbstractExpression $a , AbstractExpression $b ) {
	$this->a = $a;
	$this->b = $b;
}
}

 

AdditionOperationExpression.php

<?php
/**
* Implementa a operação interpret associada com os símbolos não terminais da árvore.
*/
class AdditionOperationExpression extends BinaryOperationExpression {
/**
 * @param	Context $context
 * @see		AbstractExpression::interpret()
 */
public function interpret( Context $context ) {
	return $this->a->interpret( $context ) + $this->b->interpret( $context );
}
}

 

SubtractionOperationExpression.php

<?php
/**
* Implementa a operação interpret associada com os símbolos não terminais da árvore.
*/
class SubtractionOperationExpression extends BinaryOperationExpression {
/**
 * @param	Context $context
 * @see		AbstractExpression::interpret()
 */
public function interpret( Context $context ) {
	return $this->a->interpret( $context ) - $this->b->interpret( $context );
}
}

 

DivisionOperationExpression.php

<?php
/**
* Implementa a operação interpret associada com os símbolos não terminais da árvore.
*/
class DivisionOperationExpression extends BinaryOperationExpression {
/**
 * @param	Context $context
 * @see		AbstractExpression::interpret()
 */
public function interpret( Context $context ) {
	$b = $this->b->interpret( $context );

	if ( $b != 0 ) {
		return $this->a->interpret( $context ) / $b;
	} else {
		throw new LogicException( 'Divisão por zero' );
	}
}
}

 

MultiplicationOperationExpression.php

<?php
/**
* Implementa a operação interpret associada com os símbolos não terminais da árvore.
*/
class MultiplicationOperationExpression extends BinaryOperationExpression {
/**
 * @param	Context $context
 * @see		AbstractExpression::interpret()
 */
public function interpret( Context $context ) {
	return $this->a->interpret( $context ) * $this->b->interpret( $context );
}
}

 

Vejamos:

 

<?php
$a = new NumericExpression( 10 );
$b = new NumericExpression( 20 );

$operation = new MultiplicationOperationExpression( $a , $b );

echo $operation->interpret( new Context() );

 

Saída:

 

200

 

Trocando de operação:

 

<?php
$a = new NumericExpression( 10 );
$b = new NumericExpression( 20 );

$operation = new DivisionOperationExpression( $a , $b );

echo $operation->interpret( new Context() );

 

Saída:

 

0.5

 

Uma expressão mais complexa: 5 * ( 3 + ( 10 / 2 ) )

 

<?php
$a = new NumericExpression(  5 );
$b = new NumericExpression(  3 );
$c = new NumericExpression( 10 );
$d = new NumericExpression(  2 );

$operation = new MultiplicationOperationExpression( $a,
new AdditionOperationExpression( $b,
	new DivisionOperationExpression( $c , $d )
)
);

echo $operation->interpret( new Context() );

 

Saída:

 

40

Compartilhar este post


Link para o post
Compartilhar em outros sites

Poutz! Olha pra que nível que uma continha aleatória elevada. :o

 

Mas pelo menos agora temos algo mais palpável sobre como utilizar o Interpreter :grin:

Compartilhar este post


Link para o post
Compartilhar em outros sites

João, primeiramente gostaria de parabenizar seu excelente trabalho!

 

Gostaria de saber se é possível você explicar qual o problema que gera a necessidade de uso deste padrão?

 

Neste caso apresentado, aparentemente criamos uma estrutura imensa para resolver um problema simples, acredito que isto foi só para demonstrar o uso, na prática não valeria a pena neste caso específico montar toda esta estrutura para efetuar estas operações. Me corrija se eu estiver errado por favor.

 

Também gostaria de saber se é possível apresentar um exemplo com uso do Context, pois não consegui entender ele.

 

Um último ponto (abusando da sua boa vontade), não entendi também o uso do método interpret() usado na NumericExpression, pois passamos como parâmetro um objeto Context que não é utilizado dentro do próprio método. No caso, em:

 

echo $operation->interpret( new Context() );

Este new Context() é passado como parâmetro para o método interpret, que é um método implementado na classe MultiplicationOperationExpression() por exemplo, que por sua vez, passa este mesmo objeto Context como parâmetro para o método interpret implementado na NumericExpression, neste caso seria o $a ou o $b. Mas é aí que não entendo, o método interpret() desta classe retorna $this->value e não faz uso do objeto Context() passado no início. Poderia me dar uma luz? rsrs

 

Seria o caso de neste método Interpret() da NumerixExpression, eu retornar algo como:

 


public function interpret( Context $context ) {
return $context->doSomethingWith($this->value);
}

??

Agradeço muito por tudo, tenho lido muito sobre patterns aqui no forum!!! Parabéns!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.