zlikavac32 / php-measure-units
PHP的度量单位实现
Requires
- php: ^8.0
- php-ds/php-ds: ^1.2
- zlikavac32/php-enum: ^4.0
Requires (Dev)
- phpspec/phpspec: ^6.1
- phpunit/phpunit: ^8.4
This package is auto-updated.
Last update: 2024-09-13 22:06:17 UTC
README
用于管理各种度量单位、数量及其之间转换的库。
目录
简介
在现实世界中,一个数字本身并没有太多的意义。我们通常将其与某个维度关联,如长度或体积。每个维度都有自己的度量单位。通过将值与维度结合,我们得到一个数量。
让我们以计算一个角度的正弦值为例。
$angle = 90; echo sin($angle);
我们得到 0.89399666360056
,这并不是1,这是一个度量单位不匹配的例子。正弦函数的实现期望提供的值是以弧度给出的,而我们是提供的以度给出的。这样的错误很容易犯,因此需要一个更好的环境。
现在让我们想象一下,我们在PHP中有一个数量的概念。
$angle = new Quantity(90, 'degc'); echo sin($angle->in('rad')->value());
现在犯前面错误的难度大大增加。如果提供的 $angle
的维度不是 rad
,这将失败。如果维度相同,那么 90
的值将转换为请求的度量单位。
我们还可以有一个直接接受数量的正弦函数。
总的来说,如果你出于某种原因需要在各种度量单位下处理数量,保持一致性很重要。因此,本库的目标是使数量和度量单位的操作更简单,并将这种一致性引入代码。
需要注意的是,这个库还没有实现维度的概念。只有度量单位的概念得到了实现。例如,弧度和球面度在SI单位术语中具有相同的表示(没有单位),但我们不能将它们相加或相减。这个库还没有实现这种区分。
安装
建议通过Composer安装。
composer require zlikavac32/php-measure-units
配置
要使用度量单位,必须构造一些服务。
use Zlikavac32\UnitsOfMeasure\Defaults; use Zlikavac32\UnitsOfMeasure\MapUnitNormalizer; use Zlikavac32\UnitsOfMeasure\NativeRuntime; use Zlikavac32\UnitsOfMeasure\SiFormParser; $baseUnits = Defaults::siBaseUnits(); $transitionMap = Defaults::siDerivedUnits() ->merge(Defaults::otherMetricUnits()); $imperialUnits = Defaults::imperialUnits(); $parser = new SiFormParser($baseUnits->merge($transitionMap->keys())->toArray(), $imperialUnits->keys()->toArray()); $normalizer = new MapUnitNormalizer( $transitionMap->merge($imperialUnits), $baseUnits ); $unitsOfMeasure = new NativeRuntime( $parser, $normalizer );
变量 $unitsOfMeasure
是度量单位的主要入口点。 NativeRuntime
实现 \Zlikavac32\UnitsOfMeasure\Runtime
,可以用来创建度量单位和数量。
默认实现是 \Zlikavac32\UnitsOfMeasure\NativeRuntime
,它需要一个 \Zlikavac32\UnitsOfMeasure\Parser
的实例和一个 \Zlikavac32\UnitsOfMeasure\Normalizer
的实例。
默认的规范化实现是 \Zlikavac32\UnitsOfMeasure\MapUnitNormalizer
,它需要一个转换映射和一组基本单位。
有解析器的两种实现。一种是使用规范SI形式,如 kg.m
或 m.s-2
(\Zlikavac32\UnitsOfMeasure\SiFormParser
),另一种是使用更符合人类习惯的形式,如 m/s
或 kg m/s2
(\Zlikavac32\UnitsOfMeasure\HumanFormUnitsParser
)。
\Zlikavac32\UnitsOfMeasure\Defaults
包含一组预定义的基本度量单位以及各种派生单位。
使用
一旦创建度量单位环境,就可以通过调用 parse(string $measureUnit)
方法创建度量单位实例,该方法返回一个 \Zlikavac32\UnitsOfMeasure\MeasureUnit
的实例。
echo (string) $unitsOfMeasure->parse('kg.m.s-2), "\n";
除了调用 parse()
之外,还可以使用数组语法来检索测量单位。
echo (string) $unitsOfMeasure['kg.m.s-2'], "\n";
操作度量单位
度量单位可以进行乘法、除法、求幂、倒数或相互转换。度量单位接口简单明了,除了in(string|MeasureUnit $measureUnit)
方法。该方法返回一个\Zlikavac32\UnitsOfMeasure\Ratio
实例。要正确定义一个比率,仅仅有一个数字是不够的。我们还需要跟踪转换是否反转了原始单位。例如,将Hz
转换为s
时,比率是一,但单位在全局上被反转。因此,将2 Hz
实际上转换为0.5 s
。
$m = $unitsOfMeasure['m']; $kg = $unitsOfMeasure['kg']; $s2 = $unitsOfMeasure['s2']; $newton = $m->multiplyBy($kg)->divideBy($s2); echo $newton->in('kN')->applyTo(5);
查看示例以获取更多信息。
数量
与其手动跟踪值及其度量单位,不如将它们配对为一个数量。
可以使用__invoke(int $value, string|MeasureUnit $measureUnit)
方法创建数量。它返回一个\Zlikavac32\UnitsOfMeasure\Quantity
实例。
echo (string) $unitsOfMeasure(3, 'm3'), "\n"; echo (string) $unitsOfMeasure(3, $unitsOfMeasure['s']), "\n";
数量也可以进行乘法、除法、求幂等操作。
$m = $unitsOfMeasure(1, 'm'); $kg = $unitsOfMeasure(1, 'kg'); $s2 = $unitsOfMeasure(1, 's2'); $newton = $m->multiplyBy($kg)->divideBy($s2); echo (string) $newton->in('kN');
在进行乘法或除法等操作时,结果度量单位不会自动简化。例如,将kg
与m
相乘,然后除以s2
,结果不会是N
。度量单位表示为N
,但它不是N
。要获得表示为N
的度量单位,必须显式调用in()
方法。
echo (string) $newton, "\n"; echo (string) $newton->in('N');
查看示例以获取更多信息。
比例
此库还支持缩放度量单位。例如,汽油消耗的度量单位可以是l/100 km
。另一个例子是流体流量,如m3/15 min
。
$gasolineConsumptionPer100Km = $unitsOfMeasure['l.100 km-1']; // How many kilometers can we make with one liter if we had consumption of 4 liters per 100 kilometers echo $gasolineConsumptionPer100Km->in('km.l-1')->applyTo(4);
在一定程度上,这可以直接用于度量单位转换。
echo $unitsOfMeasure['123 cm']->in('m')->ratio()->asFloat(), "\n"; echo $unitsOfMeasure['500 kg.6 m.2 s-2']->in('kN')->ratio()->asFloat();
不同的运行时操作可能支持不同的度量单位格式,因此可能会实现运行时,将100cm+1mm
直接解析为101 cm
。
限制
上述限制之一是,此库的用户必须提供语义检查以执行度量单位操作。如果您尝试将弧度与球面度相加,因为它们具有相同的SI单位表示,此库不会报错。
另一个限制是,此库仅处理具有常数比率的度量单位转换。换句话说,从摄氏度到开尔文的转换不支持。仍然可以提供自定义运行时以满足这一需求。
示例
您可以在示例中看到更多代码注释中的示例。