Skip to content

Commit 73e27be

Browse files
committed
Adds raising by power, and raising by power and reducing by modulus methods
1 parent cb974e8 commit 73e27be

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ElliotJReed\Maths\Exception;
6+
7+
final class InvalidExponent extends MathsException
8+
{
9+
protected $message = 'Exponent must be a whole number.';
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ElliotJReed\Maths\Exception;
6+
7+
final class InvalidPowerModulusDivisor extends MathsException
8+
{
9+
protected $message = 'Divisor must be a whole number.';
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ElliotJReed\Maths\Exception;
6+
7+
use Exception;
8+
9+
abstract class MathsException extends Exception
10+
{
11+
}

src/ElliotJReed/Maths/Number.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace ElliotJReed\Maths;
66

7+
use ElliotJReed\Maths\Exception\InvalidExponent;
8+
use ElliotJReed\Maths\Exception\InvalidPowerModulusDivisor;
9+
710
final class Number
811
{
912
private string $number;
@@ -90,6 +93,34 @@ public function modulus(int | float | string $divisorNumber): self
9093
return $this;
9194
}
9295

96+
public function raiseToPower(int | float | string $exponentNumber): self
97+
{
98+
if (\floor((float) $exponentNumber) !== (float) $exponentNumber) {
99+
throw new InvalidExponent('Exponent must be a whole number. Invalid exponent: ' . $exponentNumber);
100+
}
101+
102+
$this->number = \bcpow($this->number, (string) $exponentNumber, $this->precision);
103+
104+
return $this;
105+
}
106+
107+
public function raiseToPowerReduceByModulus(
108+
int | float | string $exponentNumber,
109+
int | float | string $divisorNumber
110+
): self {
111+
if (\floor((float) $exponentNumber) !== (float) $exponentNumber) {
112+
throw new InvalidExponent('Exponent must be a whole number. Invalid exponent: ' . $exponentNumber);
113+
}
114+
115+
if (\floor((float) $divisorNumber) !== (float) $divisorNumber) {
116+
throw new InvalidPowerModulusDivisor('Divisor must be a whole number. Invalid divisor: ' . $divisorNumber);
117+
}
118+
119+
$this->number = \bcpowmod($this->number, (string) $exponentNumber, (string) $divisorNumber, $this->precision);
120+
121+
return $this;
122+
}
123+
93124
public function isLessThan(int | float | string $number): bool
94125
{
95126
$result = \bccomp($this->number, (string) $number, $this->precision);

tests/ElliotJReed/Maths/NumberTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace ElliotJReed\Maths;
66

7+
use ElliotJReed\Maths\Exception\InvalidExponent;
8+
use ElliotJReed\Maths\Exception\InvalidPowerModulusDivisor;
79
use PHPUnit\Framework\TestCase;
810

911
final class NumberTest extends TestCase
@@ -558,6 +560,80 @@ public function testItReturnsModulusWhenBaseNumberIsAString(): void
558560
$this->assertSame(0, $number->asInteger(\PHP_ROUND_HALF_DOWN));
559561
}
560562

563+
public function testItReturnsNumberRaisedToPowerExponentWhenBaseNumberIsAnInteger(): void
564+
{
565+
$number = new Number(5);
566+
$number->raiseToPower(3);
567+
568+
$this->assertSame('125', $number->asString());
569+
$this->assertSame(125.0, $number->asFloat());
570+
$this->assertSame(125, $number->asInteger());
571+
$this->assertSame(125, $number->asInteger(\PHP_ROUND_HALF_DOWN));
572+
}
573+
574+
public function testItReturnsNumberRaisedToPowerExponentWhenBaseNumberIsAFloat(): void
575+
{
576+
$number = new Number(2.75);
577+
$number->raiseToPower(2);
578+
579+
$this->assertSame('7.5625', $number->asString());
580+
$this->assertSame(7.5625, $number->asFloat());
581+
$this->assertSame(8, $number->asInteger());
582+
$this->assertSame(8, $number->asInteger(\PHP_ROUND_HALF_DOWN)); // TODO: use a rounded number
583+
}
584+
585+
public function testItThrowsExceptionWhenExponentIsNotAWholeNumberWhenRaisingToPower(): void
586+
{
587+
$number = new Number(25);
588+
589+
$this->expectException(InvalidExponent::class);
590+
$this->expectExceptionMessage('Exponent must be a whole number. Invalid exponent: 1.5');
591+
592+
$number->raiseToPower(1.5);
593+
}
594+
595+
public function testItReturnsNumberRaisedToPowerExponentAndReducedByModulusWhenBaseNumberIsAnInteger(): void
596+
{
597+
$number = new Number(5371);
598+
$number->raiseToPowerReduceByModulus(2, 7);
599+
600+
$this->assertSame('4', $number->asString());
601+
$this->assertSame(4.0, $number->asFloat());
602+
$this->assertSame(4, $number->asInteger());
603+
$this->assertSame(4, $number->asInteger(\PHP_ROUND_HALF_DOWN));
604+
}
605+
606+
public function testItReturnsNumberRaisedToPowerExponentAndReducedByModulusWhenBaseNumberIsAString(): void
607+
{
608+
$number = new Number('5371');
609+
$number->raiseToPowerReduceByModulus(2, 7);
610+
611+
$this->assertSame('4', $number->asString());
612+
$this->assertSame(4.0, $number->asFloat());
613+
$this->assertSame(4, $number->asInteger());
614+
$this->assertSame(4, $number->asInteger(\PHP_ROUND_HALF_DOWN));
615+
}
616+
617+
public function testItThrowsExceptionWhenExponentIsNotAWholeNumberWhenRaisingToPowerAndReducingByModulus(): void
618+
{
619+
$number = new Number('5371');
620+
621+
$this->expectException(InvalidExponent::class);
622+
$this->expectExceptionMessage('Exponent must be a whole number. Invalid exponent: 2.2');
623+
624+
$number->raiseToPowerReduceByModulus(2.2, 7);
625+
}
626+
627+
public function testItThrowsExceptionWhenDivisorIsNotAWholeNumberWhenRaisingToPowerAndReducingByModulus(): void
628+
{
629+
$number = new Number('5371');
630+
631+
$this->expectException(InvalidPowerModulusDivisor::class);
632+
$this->expectExceptionMessage('Divisor must be a whole number. Invalid divisor: 7.5');
633+
634+
$number->raiseToPowerReduceByModulus(2, 7.5);
635+
}
636+
561637
public function testItReturnsTrueWhenNumberIsLessThanTheBaseNumberWhenCheckingIfNumberIsLessThanBaseNumber(): void
562638
{
563639
$number = new Number('100.01');

0 commit comments

Comments
 (0)