Improved the ARABIC function to handle short-form roman numerals
This commit is contained in:
parent
560e672b30
commit
a08415a7b5
|
@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com)
|
The format is based on [Keep a Changelog](https://keepachangelog.com)
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org).
|
and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Improved the ARABIC function to also hande short-hand roman numerals
|
||||||
|
|
||||||
## [1.11.0] - 2020-03-02
|
## [1.11.0] - 2020-03-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -61,34 +61,17 @@ class MathTrig
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the roman numeral to an arabic number
|
// Convert the roman numeral to an arabic number
|
||||||
$lookup = [
|
|
||||||
'M' => 1000, 'CM' => 900,
|
|
||||||
'D' => 500, 'CD' => 400,
|
|
||||||
'C' => 100, 'XC' => 90,
|
|
||||||
'L' => 50, 'XL' => 40,
|
|
||||||
'X' => 10, 'IX' => 9,
|
|
||||||
'V' => 5, 'IV' => 4, 'I' => 1,
|
|
||||||
];
|
|
||||||
|
|
||||||
$negativeNumber = $roman[0] === '-';
|
$negativeNumber = $roman[0] === '-';
|
||||||
if ($negativeNumber) {
|
if ($negativeNumber) {
|
||||||
$roman = substr($roman, 1);
|
$roman = substr($roman, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$arabic = 0;
|
try {
|
||||||
for ($i = 0; $i < strlen($roman); ++$i) {
|
$arabic = self::calculateArabic(str_split($roman));
|
||||||
if (!isset($lookup[$roman[$i]])) {
|
} catch (\Exception $e) {
|
||||||
return Functions::VALUE(); // Invalid character detected
|
return Functions::VALUE(); // Invalid character detected
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($i < (strlen($roman) - 1) && isset($lookup[substr($roman, $i, 2)])) {
|
|
||||||
$arabic += $lookup[substr($roman, $i, 2)]; // Detected a match on the next 2 characters
|
|
||||||
++$i;
|
|
||||||
} else {
|
|
||||||
$arabic += $lookup[$roman[$i]]; // Detected a match on one character only
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($negativeNumber) {
|
if ($negativeNumber) {
|
||||||
$arabic *= -1; // The number should be negative
|
$arabic *= -1; // The number should be negative
|
||||||
}
|
}
|
||||||
|
@ -96,6 +79,47 @@ class MathTrig
|
||||||
return $arabic;
|
return $arabic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively calculate the arabic value of a roman numeral.
|
||||||
|
*
|
||||||
|
* @param array $roman
|
||||||
|
* @param int $sum
|
||||||
|
* @param int $subtract
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected static function calculateArabic(array $roman, &$sum = 0, $subtract = 0)
|
||||||
|
{
|
||||||
|
$lookup = [
|
||||||
|
'M' => 1000,
|
||||||
|
'D' => 500,
|
||||||
|
'C' => 100,
|
||||||
|
'L' => 50,
|
||||||
|
'X' => 10,
|
||||||
|
'V' => 5,
|
||||||
|
'I' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
$numeral = array_shift($roman);
|
||||||
|
if (!isset($lookup[$numeral])) {
|
||||||
|
throw new \Exception('Invalid character detected');
|
||||||
|
}
|
||||||
|
|
||||||
|
$arabic = $lookup[$numeral];
|
||||||
|
if (count($roman) > 0 && isset($lookup[$roman[0]]) && $arabic < $lookup[$roman[0]]) {
|
||||||
|
$subtract += $arabic;
|
||||||
|
} else {
|
||||||
|
$sum += ($arabic - $subtract);
|
||||||
|
$subtract = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($roman) > 0) {
|
||||||
|
self::calculateArabic($roman, $sum, $subtract);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ATAN2.
|
* ATAN2.
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,4 +33,28 @@ return [
|
||||||
-2018,
|
-2018,
|
||||||
'-MMXVIII',
|
'-MMXVIII',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
499,
|
||||||
|
'CDXCIX'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
499,
|
||||||
|
'LDVLIV'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
499,
|
||||||
|
'XDIX'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
499,
|
||||||
|
'VDIV'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
499,
|
||||||
|
'ID'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!',
|
||||||
|
'WRONG'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue