Skip to content

Instantly share code, notes, and snippets.

@Zulcom
Created September 10, 2018 04:22
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 Zulcom/4e66480ddc5cf2b13097822ed06a238e to your computer and use it in GitHub Desktop.
Save Zulcom/4e66480ddc5cf2b13097822ed06a238e to your computer and use it in GitHub Desktop.
PHPUnit test demo related to presentation https://goo.gl/yw3U1y
<?php
namespace SfuKruto\model;
/**
* Класс-обработчик дробей
*/
class Fraction
{
/** @var int|Radical числитель */
private $numerator;
/** @var integer знаменатель */
private $denominator;
/** @var bool является радикалом */
private $isRadical;
/**
* Fraction constructor.
* @param int|Radical числитель
* @param int знаменатель
*/
public function __construct($numerator, $denominator)
{
$this->isRadical = is_a($numerator, 'SfuKruto\model\Radical');
$this->numerator = $numerator;
$this->denominator = $denominator;
$this->reduce();
}
/**
* Сокращает дробь
*/
private function reduce()
{
if (!$this->isRadical) {
$a = abs($this->numerator);
$b = abs($this->denominator);
} else {
$a = abs($this->numerator->getPerfectSquare());
$b = abs($this->denominator);
}
if ($a < $b) {
$a ^= $b;
$b ^= $a;
$a ^= $b;
}
while ($a * $b != 0) {
$tmp = $b;
try {
$b = $a % $b;
} catch (\Throwable $e) {
$b = 0;
break;
}
$a = $tmp;
}
/** @var int|float Наибольший общий делитель */
$gcd = $a + $b;
if ($this->denominator < 0) {
$gcd *= -1;
}
if (!$this->isRadical) {
$this->numerator /= $gcd;
} else {
$this->numerator->setRadicand($this->numerator->getRadicand() / ($gcd * $gcd));
}
$this->denominator /= $gcd;
}
public function __toString()
{
if ($this->denominator == 0) {
throw new \InvalidArgumentException('Не является числом!');
} else {
if (!$this->isRadical) {
$toReturn = $this->numerator;
} else {
$toReturn = $this->numerator->__toString();
}
if ($this->denominator > 1) {
$toReturn .= "/{$this->denominator}";
}
}
return $toReturn;
}
}
<?php
namespace SfuKruto\model;
/**
* Класс для обработки корней
*/
class Radical
{
/** @var int|float подкоренное выражение */
private $radicand;
/** @const string знак корня */
private $ROOT_SIGN = '√';
private $IMAGINARY_UNIT_SIGN = 'i';
/**
* Radical constructor.
* @param int|float подкоренное выражение
*/
public function __construct($radicand)
{
$this->radicand = $radicand;
}
/**
* @param int|float $radicand
*/
public function setRadicand($radicand)
{
$this->radicand = $radicand;
}
/**
* @return float|int
*/
public function getRadicand()
{
return $this->radicand;
}
public function __toString()
{
$toReturn = "";
if ($this->radicand <= 0) {
$toReturn = "{$this->IMAGINARY_UNIT_SIGN}*";
$this->radicand *= -1;
}
if ($this->radicand == 0) {
$toReturn .= "0";
} else {
$perfectSquare = $this->getPerfectSquare();
if ($perfectSquare != 1) {
$toReturn .= $perfectSquare;
}
$perfectSquare *= $perfectSquare;
if ($this->radicand != $perfectSquare) {
$toReturn .= $this->ROOT_SIGN.$this->radicand / $perfectSquare;
}
}
return $toReturn;
}
/** Получить полный квадрат числа
* @return int
*/
public function getPerfectSquare()
{
$a = abs($this->radicand);
$square = 1;
$maxDiv = floor(sqrt($a));
for ($i = 2; $i <= $maxDiv; ++$i) {
while ($a % ($i * $i) == 0) {
$a /= $i * $i;
$square *= $i;
}
$maxDiv = floor(sqrt($a));
}
return $square;
}
/** Является ли числом
* @return bool
*/
public function isInteger()
{
$s = $this->getPerfectSquare();
return ($this->radicand == $s * $s);
}
}
<?php
namespace SfuKruto\controller;
use SfuKruto\model\Radical;
use SfuKruto\model\Fraction;
class Solver
{
private $a;
private $b;
private $c;
private $note;
private $solution = [];
/**
* Solver constructor.
* @param $a
* @param $b
* @param $c
*/
public function __construct($a, $b, $c)
{
$this->a = $a;
$this->b = $b;
$this->c = $c;
$this->solve();
}
public function getFirstRoot()
{
return $this->solution['x'];
}
public function getSecondRoot()
{
return $this->solution['y'];
}
/**
* @return mixed
*/
public function getNote()
{
return $this->note;
}
/**
* @return array
*/
public function getSolution(): array
{
return $this->solution;
}
public function solve()
{
if ($this->a == 0) {
if ($this->b != 0) {
$this->note = "a = 0; уравнение вырождается в линейное:";
$this->solution['x'] = (new Fraction(-$this->c, $this->b))->__toString();
} elseif ($this->c == 0) {
$this->note = 'Все коэффициенты равны нулю';
$this->solution['x'] = 'Любое число';
} else {
$this->note = 'Нет решений';
}
} else {
$discriminant = $this->b * $this->b - 4 * $this->a * $this->c;
if ($discriminant != 0) {
$this->note = 'Два корня';
$dRoot = new Radical($discriminant);
if ($dRoot->isInteger()) {
$this->solution['x'] = (new Fraction(
-$this->b + sqrt($discriminant), 2 * $this->a
))->__toString();
$this->solution['y'] = (new Fraction(
-$this->b - sqrt($discriminant), 2 * $this->a
))->__toString();
} else {
$rational = (new Fraction(-$this->b, 2 * $this->a))->__toString();
$irrational = (new Fraction(new Radical($discriminant), 2 * $this->a))->__toString();
if ($rational == '0') {
$this->solution['x'] = $irrational;
$this->solution['y'] = "-{$irrational}";
} else {
$this->solution['x'] = "{$rational}+$irrational";
$this->solution['y'] = "{$rational}-$irrational";
}
}
} else {
$this->note = 'Дискриминант равен 0, корень один';
$this->solution['x'] = (new Fraction(-$this->b,2*$this->a))->__toString();
}
}
}
public function __toString()
{
return "{$this->note}\n x1 = {$this->solution['x']}, x2 = {$this->solution['y']}";
}
}
<?php
namespace SfuKruto\tests\controller;
use SfuKruto\controller\Solver;
use PHPUnit\Framework\TestCase;
class SolverTest extends TestCase
{
private $ROOT_SIGN = '√';
private $IMAGINARY_UNIT_SIGN = 'i';
public function testLinearEquation()
{
$solver = new Solver(0, -1, -1);
$this->assertEquals(-1, $solver->getFirstRoot());
$this->assertEquals(null, $solver->getSecondRoot());
}
public function testPerfectSquare()
{
$solver = new Solver(1, 0, -2);
$this->assertEquals("{$this->ROOT_SIGN}2", $solver->getFirstRoot());
$this->assertEquals("-{$this->ROOT_SIGN}2", $solver->getSecondRoot());
}
public function testComplexResult()
{
$solver = new Solver(1, 0, 25);
$this->assertEquals("{$this->IMAGINARY_UNIT_SIGN}*5", $solver->getFirstRoot());
$this->assertEquals("-{$this->IMAGINARY_UNIT_SIGN}*5", $solver->getSecondRoot());
}
public function testFractionResult()
{
$solver = new Solver(1, 5, -1);
$this->assertEquals("-5/2+{$this->ROOT_SIGN}29/2", $solver->getFirstRoot());
$this->assertEquals("-5/2-{$this->ROOT_SIGN}29/2", $solver->getSecondRoot());
}
public function testZero()
{
$solver = new Solver(0, 4, 0);
$this->assertEquals("0", $solver->getFirstRoot());
$this->assertEquals(null, $solver->getSecondRoot());
}
public function Small(){
$solver = new Solver(0.00001,2,1);
$this->assertEquals('-199999',$solver->getFirstRoot());
$this->assertEquals('-0.5',$solver->getSecondRoot());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment