rikudou / units
Unit converter and calculator
Requires
- php: ^7.4
- ext-bcmath: *
- lisachenko/z-engine: ^0.8.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.1
- phpstan/phpstan: ^0.12.99
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2024-10-19 23:25:53 UTC
README
This library uses the awesome lisachenko/z-engine to allow mathematical operations on objects, allowing to do stuff like this:
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Foot; $meter = new Meter(5); $feet = new Foot(15); $result = $meter + $feet; var_dump($result->getValue()); // dumps object of Rikudou\Units\Number\BigNumber which holds the value 9.572
You need to have ffi enabled and bcmath extension installed.
The units are always in the unit that's first in the operation, meaning if you wanted the result in feet you would just reverse them (or convert them, more on that below):
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Foot; $meter = new Meter(5); $feet = new Foot(15); $result = $feet + $meter; var_dump($result->getValue()); // dumps object of Rikudou\Units\Number\BigNumber which holds the value 31.40419947506561
The value is always an instance of Rikudou\Units\Number\BigNumber
which can be cast to int, float, bool and string.
Casting to int and float may be unsafe if working with large numbers.
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Number\BigNumber; $meter = new Meter(5); $value = $meter->getValue(); var_dump((int) $value); // int(5) var_dump((float) $value); // float(5) var_dump((string) $value); // string(1) "5" var_dump((bool) $value); // bool(true) $veryBigValue = $meter * PHP_INT_MAX; $value = $veryBigValue->getValue(); var_dump((string) $value); // on 64 bit correctly prints string(20) "46116860184273879035" var_dump((int) $value); // prints int(9223372036854775807) which is the value of PHP_INT_MAX on 64 bits var_dump((float) $value); // prints float(4.6116860184274E+19) which is more or less correct but not very precise // BigNumbers follow standard bool logic $number = new BigNumber(0); var_dump((bool) $number); // bool(false)
BigNumber
allows standard mathematical operations with other BigNumber
s, ints, floats, strings and objects
implementing __toString()
method. Operations always return a new instance of BigNumber
.
<?php use Rikudou\Units\Number\BigNumber; $number = new BigNumber(10); var_dump($number + $number); // BigNumber with value 20 var_dump($number + 10); // BigNumber with value 20 var_dump($number + 10.5); // BigNumber with value 20.5 var_dump($number + '10'); // BigNumber with value 20 $stringableObject = new class { public function __toString(): string { return '10'; } }; var_dump($number + $stringableObject); // BigNumber with value 20
These standard mathematical operations are supported on BigNumber
s:
- addition
- subtraction
- multiplication
- division
- exponentiation
Installation
composer require rikudou/units
Operations with units
All items of the same type can be freely added and subtracted. Additionally all units can be added, subtracted, multiplied and divided by numbers (BigNumber, string, int, float, stringable objects). Some units can also be multiplied and divided by other units where it makes sense (e.g. length units multiplied result in area units, area units divided by length units result in length units). Adding between unrelated units (like length and area) that don't make sense are not supported.
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Centimeter; $meter = new Meter(1); $centimeter = new Centimeter(10); var_dump($meter + $centimeter); // 1.1 meters var_dump($meter - $centimeter); // 0.9 meters var_dump($meter * $centimeter); // 0.1 square meters var_dump($meter / $centimeter); // error var_dump($meter * 2); // 2 meters var_dump($meter / 2); // 0.5 meters var_dump($meter ** 2); // 1 square meter var_dump($meter ** 3); // 1 cubic meter var_dump($meter ** 4); // error $squareMeter = $meter ** 2; var_dump($squareMeter / $meter); // 1 meter var_dump($squareMeter * $meter); // 1 cubic meter var_dump($squareMeter * $squareMeter); // error var_dump($squareMeter / $squareMeter); // error $cubicMeter = $meter ** 3; var_dump($cubicMeter / $squareMeter); // 1 meter var_dump($cubicMeter / $meter); // 1 square meter
You can also freely work with units from different systems:
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Yard; $meter = new Meter(1); $yard = new Yard(1); var_dump($meter + $yard); // 1.9144 meters var_dump($meter - $yard); // 0.0856 meters var_dump($meter * $yard); // 0.9144 square meters var_dump($yard + $meter); // 2.0936132983377 yards
The order of operations matters as the first unit is the one result will be converted to. If you want to convert the
result to different units you can use the UnitConverter
object:
<?php use Rikudou\Units\Converter\UnitConverter; use Rikudou\Units\Unit\Length\Foot; use Rikudou\Units\Unit\Length\Yard; use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Temperature\Celsius; use Rikudou\Units\Unit\Temperature\Fahrenheit; $converter = new UnitConverter(); $yards = new Yard(10); $feet = new Foot(10); $result = $yards + $feet; $meters = $converter->convert($result, Meter::class); var_dump($meters); // 12.19199999999999 meters $celsius = new Celsius(100); var_dump($converter->convert($celsius, Fahrenheit::class)); // 212 fahrenheits
Supported Units
Length
- millimeter
- centimeter
- meter
- kilometer
- inch
- foot
- yard
- mile
Area
- square millimeter
- square centimeter
- square meter
- square kilometer
- square foot
- acre
Volume
- cubic millimeter
- cubic centimeter
- cubic meter
- cubic kilometer
- cubic foot
- litre
- millilitre
- centilitre
- decilitre
Temperature
- celsius
- fahrenheit
- kelvin
If you'd like another unit supported, please create an issue.
Comparing
You can compare related units together:
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Centimeter; use Rikudou\Units\Unit\Temperature\Celsius; use Rikudou\Units\Unit\Temperature\Fahrenheit; $meter = new Meter(1); $centimeters = new Centimeter(100); var_dump($meter > $centimeters); // false var_dump($meter < $centimeters); // false var_dump($meter == $centimeters); // true var_dump($meter >= $centimeters); // true var_dump($meter <= $centimeters); // true $celsius = new Celsius(100); $fahrenheit = new Fahrenheit(100); var_dump($celsius > $fahrenheit); // true
The same works for BigNumber
s:
<?php use Rikudou\Units\Number\BigNumber; $number = new BigNumber(5); var_dump($number > 4); // true var_dump($number > 6); // false var_dump($number > 4.5); // true var_dump($number > '4'); // true var_dump($number > new BigNumber(3)); // true
String Casting
When a unit is cast to a string, the value and unit is printed:
<?php use Rikudou\Units\Unit\Length\Meter; use Rikudou\Units\Unit\Length\Inch; use Rikudou\Units\Unit\Length\Foot; $meters = new Meter(5); $metersSquared = $meters ** 2; $metersCubic = $meters ** 3; $inches = new Inch(5); $feet = new Foot(3.5); var_dump((string) $meters); // string(3) "5 m" var_dump((string) $metersSquared); // string(6) "25 m²" var_dump((string) $metersCubic); // string(7) "125 m³" var_dump((string) $inches); // string(4) "5″" var_dump((string) $feet); // string(8) "3′6″"
As you can see, the feet have a special casting where decimals are converted to inches.