riimu / kit-baseconversion
任意精度数字基数转换库
Requires
- php: >=5.6.0
- ext-gmp: *
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.3
- phpunit/phpunit: ^5.7 || ^6.2
- squizlabs/php_codesniffer: ^3.0
README
BaseConversion 是一个PHP库,用于转换数字基数,类似于PHP内置函数 base_convert()
。然而,与内置函数不同,这个库不受32位整数的限制,能够转换任意精度的数字。这个库还支持分数的转换,并在数字基数方面提供了更多的自定义。
为了优化大数的转换,这个库还采用了两种不同的转换策略。在某些情况下,可以通过简单地用其他基数的数字替换数字来转换数字(例如,将基数从2转换为16)。这比另一种策略快得多,后者只是使用任意精度整数算术来计算新数字。
可以使用Apigen生成的API文档,可以在以下网址在线阅读: http://kit.riimu.net/api/baseconversion/
要求
- 最低支持的PHP版本是 5.6
- 该库依赖于以下PHP扩展
gmp
(仅需要IDN支持)
安装
使用Composer安装
安装此库最简单的方法是使用Composer处理您的依赖项。为了通过Composer安装此库,只需遵循以下两个步骤
-
通过在项目根目录中运行Composer的 命令行安装 来获取
composer.phar
。 -
一旦运行了安装脚本,您应该在项目根目录中拥有
composer.phar
文件,并且可以运行以下命令php composer.phar require "riimu/kit-baseconversion:^1.2"
通过Composer安装此库后,您可以通过包含Composer在安装过程中生成的 vendor/autoload.php
文件来加载库。
添加库作为依赖项
如果您已经熟悉如何使用Composer,您还可以通过将以下 composer.json
文件添加到您的项目中并运行 composer install
命令来将库作为依赖项添加
{ "require": { "riimu/kit-baseconversion": "^1.2" } }
手动安装
如果您不希望使用Composer加载库,您也可以通过下载 最新版本 并将 src
文件夹提取到您的项目中手动下载库。然后,您可以将提供的 src/autoload.php
文件包含进来以加载库类。
使用
使用此库最方便的方法是通过 BaseConverter
类提供的 baseConvert()
静态方法。在大多数情况下,它的工作方式与 base_convert()
相同。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('A37334', 16, 2); // outputs: 101000110111001100110100
该方法接受负数和分数,方式相同。可以使用可选的第四个参数来定义转换的精度。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('-1BCC7.A', 16, 10) . PHP_EOL; // outputs: -113863.625 echo BaseConverter::baseConvert('-1BCC7.A', 16, 10, 1); // outputs: -113863.6
静态方法只是创建 BaseConvert
实例并调用 setPrecision()
和 convert()
方法的方便包装。如果您需要转换多个数字,以非静态方式调用对象更有效。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; $converter = new BaseConverter(16, 10); echo $converter->convert('A37334') . PHP_EOL; // outputs: 10711860 echo $converter->convert('-1BCC7.A') . PHP_EOL; // outputs: -113863.625 $converter->setPrecision(1); echo $converter->convert('-1BCC7.A'); // outputs: -113863.6
如果提供的数字包含不属于定义的数字基数的无效数字,则方法将返回 false。
转换分数
虽然这个库支持分数的转换,但重要的是要理解,分数不能像整数一样总是从一种数制准确转换为另一种数制。这是由于并非所有分数都可以在另一种数制中表示。
例如,假设我们在3进制中有数字0.1。这等于10进制中的1/3。然而,如果你将1/3表示为十进制数,你会得到无限循环的'0.3333...'。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('0.1', 3, 10) . PHP_EOL; // outputs: 0.33 echo BaseConverter::baseConvert('0.1', 3, 10, 6) . PHP_EOL; // outputs: 0.333333 echo BaseConverter::baseConvert('0.1', 3, 10, 12); // outputs: 0.333333333333
由于这种行为,可以设置用于不精确分数转换的精度。正如前一个例子所示,精度值定义了结果数字的最大位数。结果可能有更少的位数,但如果使用少量数字可以准确转换数字,则可能如此。如果转换器知道它可以准确转换分数,则可以完全忽略精度。
精度值还有一个替代定义。如果精度为0或负数,则结果数字的最大位数基于原始数字的精度。如果精度为0,则结果数字将具有与原始数字相同精度的位数。负数将简单地增加位数。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('0.A7', 16, 10, 0) . PHP_EOL; // outputs: 0.652 echo BaseConverter::baseConvert('0.A7', 16, 10, -2); // outputs: 0.65234
在前一个例子中,原始数字是16进制中的0.A7
。16进制中有两位小数的数字可以表示精度为1/(16 * 16) == 1/256
的数字。要在10进制中用相同精度表示小数部分,我们需要至少3位数字,因为两位数字只能表示精度为1/100
的数字。
库默认使用的精度值是-1
。还应注意,最后一位数字不会四舍五入(因为这会导致某些情况下结果不一致)。
大小写敏感
为了使用户与库的交互更加方便,库以不区分大小写的方式处理所有数字,除非数字基禁止这样做。例如,16进制可以不区分大小写处理,因为它只定义了数字0-9A-F
的值。然而,62进制不能不区分大小写处理,因为字母如A
和a
有不同的值。
返回的数字将始终尊重数字基定义的字符大小写。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('7BFA11', 16, 12) . PHP_EOL; // outputs: 2879B29 echo BaseConverter::baseConvert('7bfa11', 16, 12); // outputs: 2879B29
自定义数字基
这个库的一个特点是它允许比base_convert()
更好的数字基自定义。在大多数情况下,你可能会使用简单的整数,如10
或16
来定义数字基。然而,这个整数的尺寸没有限制。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('7F', 16, 1024) . PHP_EOL; // outputs: #0127 echo BaseConverter::baseConvert('5Glm1z', 64, 512); // outputs: #456#421#310#371
然而,对于大的数字基,数字只是由一个由#
和数字值组成的字符串表示。每当使用整数定义数字基时,数字遵循以下规则
- 等于或小于62的基使用字符串
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
中的数字 - 64进制的数字使用base64标准中的数字,即
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
- 等于或小于256的其他基使用字节作为数字,字节值表示数字值。
- 大基使用由
#
和数字值组成的字符串作为数字(字符串的长度取决于最大的数字值)。
除了使用整数定义数字基数之外,还可以使用字符串来定义数字基数。字符串中的每个字符代表一个数字,每个字符的位置代表它的值。例如,十六进制基数可以定义为 0123456789ABCDEF
。以这种方式定义数字基数还可以更容易地获取特定情况的最终结果。例如
<?php require 'vendor/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('101100011101', '01', 16) . PHP_EOL; // outputs: B1D echo BaseConverter::baseConvert('101100011101', 2, '0123456789abcdef'); // outputs: b1d
还可以使用数组定义数字基数,这是第三种方法。这种方法可以提供更大的基数自定义。数组中的每个值代表一个数字,索引表示其值。例如
<?php require 'src/autoload.php'; use Riimu\Kit\BaseConversion\BaseConverter; echo BaseConverter::baseConvert('22', 10, ['nil', 'one']) . PHP_EOL; // outputs: oneniloneonenil echo BaseConverter::baseConvert('187556', 10, ['-', '-!', '-"', '-#', '-¤', '-%']); // outputs: -¤---¤-!-%-"
致谢
本库版权所有(c)2013-2017 Riikka Kalliomäki。
有关许可和复制信息,请参阅LICENSE。