zlikavac32/php-measure-units

PHP的度量单位实现

0.3.0 2021-04-13 14:32 UTC

This package is auto-updated.

Last update: 2024-09-13 22:06:17 UTC


README

Build Status

用于管理各种度量单位、数量及其之间转换的库。

目录

  1. 简介
  2. 安装
  3. 配置
  4. 使用
    1. 操作度量单位
    2. 数量
    3. 比例
  5. 限制
  6. 示例

简介

在现实世界中,一个数字本身并没有太多的意义。我们通常将其与某个维度关联,如长度或体积。每个维度都有自己的度量单位。通过将值与维度结合,我们得到一个数量。

让我们以计算一个角度的正弦值为例。

$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.mm.s-2\Zlikavac32\UnitsOfMeasure\SiFormParser),另一种是使用更符合人类习惯的形式,如 m/skg 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');

在进行乘法或除法等操作时,结果度量单位不会自动简化。例如,将kgm相乘,然后除以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单位表示,此库不会报错。

另一个限制是,此库仅处理具有常数比率的度量单位转换。换句话说,从摄氏度到开尔文的转换不支持。仍然可以提供自定义运行时以满足这一需求。

示例

您可以在示例中看到更多代码注释中的示例。