1
\$\begingroup\$

Input: any integer

Output: that integer in number format (commas) with a leading a or an as appropriate with the rules of English

After a bit of groping around I hacked out the following PHP function, and am looking for any advice on code structure and optimization. Thank you!

function prefixAAnToNumber($num) {
    $prefixAn = array(8, 11, 18, '8', '11', '18');
    $verAn = 'an ' . number_format($num);
    $verA = 'a ' . number_format($num);

    if (in_array($num,$prefixAn)) {
        return $verAn;
    } else if (strlen($num) > 1) {
        $numComma = number_format($num);
        if (substr($numComma,0,1) == '8') {
            return $verAn;
        } else if (in_array(substr($numComma,0,2), $prefixAn) && substr($numComma,2,1) == ',') {
            return $verAn;
        } else {
            return $verA;
        }
    } else {
        return $verA;
    }
}

Example usage:

$num = 11;
for ($i = 0; $i < 10; ++$i) {
    echo '<p>'.$num.' -> "';
    echo prefixAAnToNumber($num);
    echo ' kg shipment"</p>';
    $num = $num * 10;
}

Output:

11 -> "an 11 kg shipment"

110 -> "a 110 kg shipment"

1100 -> "a 1,100 kg shipment"

11000 -> "an 11,000 kg shipment"

110000 -> "a 110,000 kg shipment"

1100000 -> "a 1,100,000 kg shipment"

11000000 -> "an 11,000,000 kg shipment"

110000000 -> "a 110,000,000 kg shipment"

1100000000 -> "a 1,100,000,000 kg shipment"

11000000000 -> "an 11,000,000,000 kg shipment"
\$\endgroup\$
4
  • \$\begingroup\$ Not a function, but a component made for such jobs: php.net/manual/en/class.numberformatter.php \$\endgroup\$
    – hakre
    Jan 6, 2012 at 16:31
  • \$\begingroup\$ "1,100" can go either way depending on whether you pronounce it "thousand one hundred" or "eleven hundred". I'd opt for the second, so my expected function results are different from yours. \$\endgroup\$
    – hvd
    Jan 8, 2012 at 21:06
  • \$\begingroup\$ @hvd - you're correct, of course. I chose to interpret it as "one thousand one hundred" to simplify my code, even though I'd read it as "eleven hundred" in casual speech. \$\endgroup\$
    – Drew
    Jan 9, 2012 at 1:32
  • \$\begingroup\$ @hakre - thanks for the link. I assumed something existed already either in the core function set or on phpclasses.org, but I wanted to write the function as a learning exercise. I'm glad I did, the answers reveal that my formatting and logic layout still needs a lot of work! \$\endgroup\$
    – Drew
    Jan 9, 2012 at 1:33

2 Answers 2

2
\$\begingroup\$

Rather than having many return statements I would keep the logic that determines whether it should be 'a' or 'an' together. I think it is actually easier to understand reading the ANDs and ORs than spread out if and else statements.

I prefer not to create temporary variables that are not used for anything - so I wouldn't create $verA and $verAn. I do however create a variable for $numComma. By having this we avoid calling number_format more than is necessary.

This is how it looks my way:

function prefixAAnToNumber($num)
{
    $prefixAn = array(8, 11, 18, '8', '11', '18');
    $numComma = number_format($num);

    if (in_array($num, $prefixAn) ||
    (strlen($num) > 1 &&
     (substr($numComma, 0, 1) == '8' ||
      (in_array(substr($numComma, 0, 2), $prefixAn) &&
       substr($numComma, 2, 1) == ','))))
    {
        return 'an ' . $numComma;
    }

    return 'a ' . $numComma;
}
\$\endgroup\$
2
\$\begingroup\$

I don't know if you have noticed but all numbers that start with an an have the numbers in the array before the comma.

So what you can do:

function prefixAAnToNumber($num) {
    $prefixAn = array(8, 11, 18, '8', '11', '18');
    $number = number_format($num);
    $numberSplit = explode(',', $number);
    $a = 'a';
    if(in_array($numberSplit[0], $prefixAn)
        || substr($number,0,1) == '8')
         $a .= 'n';
    return "$a $number";
}

Demo: http://codepad.org/bXAnr3Tz

Output:

11 -> "an 11 kg shipment"
110 -> "a 110 kg shipment"
1100 -> "a 1,100 kg shipment"
11000 -> "an 11,000 kg shipment"
110000 -> "a 110,000 kg shipment"
1100000 -> "a 1,100,000 kg shipment"
11000000 -> "an 11,000,000 kg shipment"
110000000 -> "a 110,000,000 kg shipment"
1100000000 -> "a 1,100,000,000 kg shipment"
11000000000 -> "an 11,000,000,000 kg shipment"
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.