一个简单的 PHP 罗马数字库
该库包含几个简单的过滤器,用于将带有罗马数字的string
转换为将输入表示为十进制的int
,并将十进制int
转换为带有罗马数字作为结果的string
。
use Romans Filter RomanToInt ;
$ filter = new RomanToInt ();
$ result = $ filter -> filter ( ' MCMXCIX ' ); // 1999
use Romans Filter IntToRoman ;
$ filter = new IntToRoman ();
$ result = $ filter -> filter ( 1999 ); // MCMXCIX
该包使用 Composer 作为默认存储库。您可以安装它,在composer.json
的require
部分添加包名称,指向最后一个稳定版本。
{
"require" : {
"wandersonwhcr/romans" : " ^1.0 "
}
}
此外,罗马书使用语义版本控制。以下软件包版本支持这些 PHP 版本:
1.0.*
:PHP ^7.0
(奥古斯都)1.1.*
: PHP ^7.0
(提比略)1.2.*
: PHP >=7.4
(卡利古拉)1.3.*
: PHP >=7.4
(克劳迪斯)1.4.*
: PHP >=7.4
(Nero)1.5.*
: PHP >=8.0
(Galba) 该库可以用作项目的依赖项,使与库或框架的集成更容易。如果您想在此列表中添加更多项目,请打开问题或创建拉取请求,并按字母顺序添加您的项目。
Romans
包使用 Lexer-Parser 方法和确定性有限自动机 (DFA),使用 Grammar Token 库将罗马数字转换为int
。
use Romans Grammar Grammar ;
use Romans Lexer Lexer ;
use Romans Parser Parser ;
$ grammar = new Grammar ();
$ lexer = new Lexer ( $ grammar );
$ parser = new Parser ( $ grammar );
$ tokens = $ lexer -> tokenize ( ' MCMXCIX ' );
/*
$tokens = [
0 => 'M' // Grammar::T_M
1 => 'C', // Grammar::T_C
2 => 'M', // Grammar::T_M
3 => 'X', // Grammar::T_X
4 => 'C', // Grammar::T_C
5 => 'I', // Grammar::T_I
6 => 'X', // Grammar::T_X
];
*/
$ result = $ parser -> parse ( $ tokens ); // 1999
过滤器RomanToInt
使用 Lexer 对输入进行标记,并使用 Parser 构建int
数字。当发现错误时,词法分析器或解析器会抛出异常,以使用特定代码通知问题。
use Romans Filter RomanToInt ;
use Romans Lexer Exception as LexerException ;
use Romans Parser Exception as ParserException ;
$ filter = new RomanToInt ();
try {
$ filter -> filter ( $ input );
} catch ( LexerException $ e ) {
// Unknown Token (LexerException::UNKNOWN_TOKEN)
} catch ( ParserException $ e ) {
// Invalid Token Type (Not String) (ParserException::INVALID_TOKEN_TYPE)
// Unknown Token (ParserException::UNKNOWN_TOKEN)
// Invalid Roman (ParserException::INVALID_ROMAN)
}
您可以使用此结构来验证罗马数字,添加try..catch块来检查$input
是否有效。此外,您还可以验证是否可以使用IntToRoman
过滤器将int
过滤为 Roman。
use Romans Filter IntToRoman ;
use Romans Filter Exception as FilterException ;
$ filter = new IntToRoman ();
try {
$ filter -> filter ( $ input );
} catch ( FilterException $ e ) {
// Invalid Integer (< 0) (FilterException::INVALID_INTEGER)
}
零值表示为string
"N"
,即nulla或nihil的首字母,拉丁词“无”(请参阅参考资料)。
use Romans Filter RomanToInt ;
use Romans Filter IntToRoman ;
$ filter = new RomanToInt ();
$ result = $ filter -> filter ( ' N ' ); // 0 (Zero)
$ filter = new IntToRoman ();
$ result = $ filter -> filter ( 0 ); // N
该包使用 PSR-6 缓存接口来改进执行,主要是使用缓存库的循环(如while
或foreach
)。可以使用任何 PSR-6 实现,我们建议使用 Symfony Cache 包。
use Romans Filter IntToRoman ;
use Romans Filter RomanToInt ;
use Symfony Component Cache Adapter ArrayAdapter ;
$ cache = new ArrayAdapter ();
$ filter = new RomanToInt ();
$ filter -> setCache ( $ cache );
$ result = $ filter -> filter ( ' MCMXCIX ' ); // 1999
$ result = $ filter -> filter ( ' MCMXCIX ' ); // 1999 (from cache)
$ filter = new IntToRoman ();
$ filter -> setCache ( $ cache );
$ result = $ filter -> filter ( 1999 ); // MCMXCIX
$ result = $ filter -> filter ( 1999 ); // MCMXCIX (from cache)
您可以使用 Docker Compose 构建映像并运行容器来开发和测试此包。
docker-compose build
docker-compose run --rm romans composer install
docker-compose run --rm romans composer test
本节介绍此包用于将罗马数字转换为int
的技术,反之亦然。
选择 Lexer-Parser 方法是因为罗马数字的验证和读取更加简单:Lexer 负责读取输入并将其转换为标记,在字符级别验证内容;解析器负责将 token 转换为数字,在位置级别验证内容并通过 DFA 转换为int
。
维基百科说,“词法分析是将字符序列转换为标记序列的过程”,“是表示词位的结构,它明确地表明其出于解析目的的分类”。维基百科甚至说“解析或语法分析是分析符合形式语法规则的符号的过程”。
这种结构使得开发负责读取输入string
的结构变得更容易,根据特定的字符集及其在输入中的位置将其转换为另一个结构。
DFA 的开发是为了检查带有罗马数字的string
是否有效。选择这种技术是因为其他实现只是简单地转换输入而不检查规则,例如按顺序检查四个字符。
当前的自动机定义声明如下。
M = (Q, Σ, δ, q0, F)
Q = { a, b, c, d, e, f, g, y, z }
Σ = { I, V, X, L, C, D, M, N }
q0 = g
F = { z }
z -> ε
y -> $z
a -> y | Iy | IIy | IIIy
b -> a | IVy | Va | IXy
c -> b | Xb | XXb | XXXb
d -> c | XLb | Lc | XCb
e -> d | Cd | CCd | CCCd
f -> e | CDd | De | CMd
g -> f | Ny | Mg
该软件包是开源的,可根据许可证中所述的 MIT 许可证使用。