87 lines
2.0 KiB
PHP
87 lines
2.0 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Scientific;
|
||
|
|
||
|
use InvalidArgumentException;
|
||
|
|
||
|
abstract class Quantity
|
||
|
{
|
||
|
/*
|
||
|
* https://en.wikipedia.org/wiki/Metric_prefix
|
||
|
*/
|
||
|
private const METRIC_PREFIXES = [
|
||
|
'yotta' => 'Y',
|
||
|
'zetta' => 'Z',
|
||
|
'exa' => 'E',
|
||
|
'peta' => 'P',
|
||
|
'tera' => 'T',
|
||
|
'giga' => 'G',
|
||
|
'mega' => 'M',
|
||
|
'kilo' => 'k',
|
||
|
'hecto' => 'h',
|
||
|
'deca' => 'da',
|
||
|
'unit' => '',
|
||
|
'deci' => 'd',
|
||
|
'centi' => 'c',
|
||
|
'milli' => 'm',
|
||
|
'micro' => 'μ',
|
||
|
'nano' => 'n',
|
||
|
'pico' => 'p',
|
||
|
'femto' => 'f',
|
||
|
'atto' => 'a',
|
||
|
'zepto' => 'z',
|
||
|
'yocto' => 'y',
|
||
|
];
|
||
|
|
||
|
abstract protected function getSymbol(): string;
|
||
|
|
||
|
abstract protected function getName(): string;
|
||
|
|
||
|
public function __construct(
|
||
|
private Unit $value
|
||
|
)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
final public static function fromValue(float $value): static
|
||
|
{
|
||
|
return new static(new Unit($value));
|
||
|
}
|
||
|
|
||
|
final public function getValue(): Unit
|
||
|
{
|
||
|
return $this->value;
|
||
|
}
|
||
|
|
||
|
final public function format(string $prefix = 'auto'): string
|
||
|
{
|
||
|
if ($prefix === 'auto') {
|
||
|
$prefix = $this->getAppropriatePrefix();
|
||
|
} else if (!method_exists($this->value, $prefix)) {
|
||
|
throw new InvalidArgumentException('Invalid size: ' . $prefix);
|
||
|
}
|
||
|
|
||
|
$value = $this->value->{$prefix}();
|
||
|
$prefix = self::METRIC_PREFIXES[$prefix] ?? '?';
|
||
|
$symbol = $this->getSymbol();
|
||
|
|
||
|
return sprintf('%.3g %s%s', $value, $prefix, $symbol);
|
||
|
}
|
||
|
|
||
|
private function getAppropriatePrefix(): string
|
||
|
{
|
||
|
foreach (array_keys(self::METRIC_PREFIXES) as $prefix) {
|
||
|
$value = $this->value->{$prefix}();
|
||
|
if ($value >= 1. && $value < 1000.) {
|
||
|
return $prefix;
|
||
|
}
|
||
|
}
|
||
|
return 'unit';
|
||
|
}
|
||
|
|
||
|
public function __toString(): string
|
||
|
{
|
||
|
return $this->format();
|
||
|
}
|
||
|
}
|