Tuesday, February 21, 2012

PHP - number formatting using letters

Number formatting using letters, in PHP:

define('PR_NFORMAT_DEC_SEPARATOR', '.'); // decimals separator
define('PR_NFORMAT_THS_SEPARATOR', ','); // thousands separator

/**
 *
 * Formatting numbers using letters; ex: 1066345732 becomes 1.07B
 * @param float $fValue
 * @param int $nSupportedDecimals
 * @return formatted string
 */
function customNumberFormatLetters($fValue, $nSupportedDecimals = 2) {
   
    if(!preg_match('`^[0-9\.]+$`', $fValue)) {
        return $fValue;
    }
   
    // get rid of decimals
    $fValue = round($fValue);
   
    // supported cases !!! order is IMPORTANT !!! the cases are teste in this order
    $aCases = array(
        array('no_chars' => 9, 'letter' => 'B'), // billions
        array('no_chars' => 6, 'letter' => 'M'), // millions
    );
   
    $sNumberNice = $fValue;
   
    // test suppoort cases
    foreach($aCases as $aCase) {
        if($fValue > (int)str_repeat('9', $aCase['no_chars'])) {
            $fValue = $fValue / pow(10, $aCase['no_chars']);
            if($nSupportedDecimals > 0) {
                $fValue = $fValue * pow(10, $nSupportedDecimals);
                $fValue = round($fValue);
                $fValue = $fValue / (pow(10, $nSupportedDecimals));
            } else {
                $fValue = round($fValue);
            }
            $sNumberNice = number_format($fValue, $nSupportedDecimals, PR_NFORMAT_DEC_SEPARATOR, PR_NFORMAT_THS_SEPARATOR);
            $sNumberNice = eraseEndingZeros($sNumberNice);
            $sNumberNice .= $aCase['letter'];
            break;
        }
    }
   
    return $sNumberNice;
}

function eraseEndingZeros($fValueFormatted) {
    // erase all ending zeros:
    $aNparts = explode(PR_NFORMAT_DEC_SEPARATOR, $fValueFormatted);
    if(count($aNparts) == 2) {
        if(strlen($aNparts[1]) === 0 || preg_match('`^0+$`', $aNparts[1])) {
            $fValueFormatted = $aNparts[0];
        } elseif(strlen($aNparts[1]) === 1 && (string)$aNparts[1] !== '0') {
            $fValueFormatted = $aNparts[0] . PR_NFORMAT_DEC_SEPARATOR . $aNparts[1];
        } else {
            $aNparts[1] = preg_replace('`^([0-9]+)([1-9])(0+)$`', '$1$2', $aNparts[1]);
            $fValueFormatted = $aNparts[0] . PR_NFORMAT_DEC_SEPARATOR . $aNparts[1];
        }
    }
    return $fValueFormatted;
}

No comments: