9
\$\begingroup\$

This is my 1st time developing PHP code and I am only 13 years old. I have experience in other programming languages like lua, python, and c++.

This is a simple Number to Roman Numeral code I made for my mom because she had a hard time making herself one. Below is my code. Don't mind the names of the variables.

<?php
 $NumberRomanNumeral = array(
 1 => array(
 "RomanNumeral" => "I",
 "NearestNum" => null
 ),
 5 => array(
 "RomanNumeral" => "V",
 "NearestNum" => 4
 ),
 10 => array(
 "RomanNumeral" => "X",
 "NearestNum" => 9
 ),
 50 => array(
 "RomanNumeral" => "L",
 "NearestNum" => 40
 ),
 100 => array(
 "RomanNumeral" => "C",
 "NearestNum" => 90
 ),
 500 => array(
 "RomanNumeral" => "D",
 "NearestNum" => 400
 ),
 1000 => array(
 "RomanNumeral" => "M",
 "NearestNum" => 900
 ),
 );
 
 function separateNumberIntoUnits($n) {
 $separated = str_split($n,1);
 for ($i = 0;$i <= count($separated)-1; $i++){
 $currentNum = $separated[$i];
 $length = count($separated) - $i;
 $separated[$i] = str_pad($currentNum, $length, "0");
 }
 return $separated;
 } 
 
 function getClosestNum($numToFind){
 //echo($numToFind);
 global $NumberRomanNumeral;
 $closestNum = null;
 $foundKey = null;
 $closestMag = null;
 $differenceArray = array();
 $numLeft = null;
 if ($numToFind == 0) {
 return null;
 }
 foreach($NumberRomanNumeral as $num => $data){
 array_push($differenceArray, $data["NearestNum"]);
 }
 foreach($NumberRomanNumeral as $num => $data){
 $currentIndex = array_search($num,array_keys($NumberRomanNumeral));
 $romanNumeral = $data["RomanNumeral"];
 $differenceToSum = $data["NearestNum"];
 $previousDifferenceToSum = null;
 if ($num != 1){
 $previousDifferenceToSum = $differenceArray[$currentIndex-1];
 }
 $mag = $num - $numToFind;
 if ($mag < 0){
 $mag *= -1;
 }
 if ($numToFind == $num){
 $closestNum = $num;
 $foundKey = $romanNumeral;
 break;
 }elseif($numToFind == $differenceToSum){
 $closestNum = $num;
 $foundKey = $romanNumeral;
 break;
 }
 if ($closestMag == null){
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 } else {
 if ($mag < $closestMag && $mag > $previousDifferenceToSum) {
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 }
 }
 }
 $numLeft = $numToFind - $closestNum;
 if ($numLeft < 0){
 $numLeft *= -1;
 }
 return array($closestNum, $foundKey, $numLeft);
 }
 
 function num2RomanNumeral($num, &$string){
 if ($num != null || $num != 0){
 $numArray = separateNumberIntoUnits($num);
 foreach($numArray as $splitNum){
 $data = getClosestNum($splitNum);
 if ($data != null){
 $closestNumber = $data[0]; 
 $foundRomanNumeral = $data[1];
 $numLeft = $data[2];
 if ($splitNum > $closestNumber){
 $string = $string.$foundRomanNumeral;
 if ($numLeft > 0){
 num2RomanNumeral($numLeft, $string);
 }
 }elseif($splitNum < $closestNumber){
 if ($numLeft > 0){
 num2RomanNumeral($numLeft, $string);
 }
 $string = $string.$foundRomanNumeral;
 }else{
 if ($numLeft > 0){
 num2RomanNumeral($numLeft, $string);
 }
 $string = $string.$foundRomanNumeral;
 }
 
 }
 }
 }
 }
 
 $romanNumeralText = "";
 num2RomanNumeral(4212, $romanNumeralText);
 echo $romanNumeralText;
?>

I would appreciate if you give some tips and some things that would make the code better.

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
asked Sep 21, 2022 at 11:56
\$\endgroup\$
1

1 Answer 1

7
\$\begingroup\$

For a beginner it seems fine. There are some improvements that can be made. The points below are analysis of the given code.

Obviously there are examples of simpler implementations to convert numbers to Roman numeral format - e.g. see answers to Numbers to Roman Numbers with php on Stack Overflow. While I wouldn't expect a beginner to write a succinct and optimized function, they are out there for the reader to compare.

Avoid Global variables

The first thing I spot is this line near the beginning of getClosestNum()

global $NumberRomanNumeral;

Global variables have more negative aspects than positives. Since that variable is never re-assigned it can be declared as a constant instead of a variable. Then there is no need to reference a global variable.

Coding Style can be changed to be idiomatic

I would not expect a beginner to write code that always adheres to a standard coding style, but there are recommended styles that many PHP developers write code to be inline with. One popular style guide is PSR-12. It has many conventions for readability and robust code. There are 54 errors and 1 warning for the code above. Many of the errors concern spacing between operators, tokens, etc.

For example, instead of:

}elseif($numToFind == $differenceToSum){

Idiomatic PHP code would be spaced like this:

} elseif ($numToFind == $differenceToSum) {

Array syntax can be simplified

There isn't anything wrong with using array() but as of the time of writing, there is currently active support for versions 8.0 and 8.1 of PHP, and since PHP 5.4 arrays can be declared with short array syntax (PHP 5.4).

So lines like:

$differenceArray = array();

can be simplified like this:

$differenceArray = [];

Variable gets overwritten

The seventh line of getClosestNum() is:

$numLeft = null;

Then towards the end of the function, that same variable is assigned with the difference of two other variables.

$numLeft = $numToFind - $closestNum;

This makes the first assignment (to null) superfluous. That line can be removed.

Extra indentation level can be eliminated

Near the end of getClosestNum() are these blocks of code:

 if ($closestMag == null) {
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 } else {
 if ($mag < $closestMag && $mag > $previousDifferenceToSum) {
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 }
 }

The second if (within the else) can be changed to an elseif:

 if ($closestMag == null) {
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 } elseif ($mag < $closestMag && $mag > $previousDifferenceToSum) {
 $closestNum = $num;
 $closestMag = $mag;
 $foundKey = $romanNumeral;
 }

This allows for one less indentation level for the lines within the else block.

answered Sep 21, 2022 at 17:55
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.