units = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'); $this->teens = array('ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'); $this->tens = array(2 => 'twenty', 'thirty', 'fourty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'); $this->suffix = array('thousand', 'million', 'billion', 'trillion', 'quadrillion'); } /** * Returns appropriate text for given number. Despite * appearances the number should (though isn't required) be * passed in as a string. This allows large numbers to be * converted. Integers are handled just fine though. * Negative numbers are handled fine. * * The billion/trillion etc suffixes are done using the American * style (eg 9 zeros for billion, 12 for trillion), which albeit * being mathmetically incorrect, is (I believe) the commonly * accepted norm. Since this code was written for the purpose * of validating human vs spider form submissions, this is the * more appropriate way to go. * * @param string $int The number to convert. Optional. * @return text Resulting text */ function ToString($int) { // Check for purely numeric chars if (!preg_match('#^[\d.]+$#', $int)) { echo('Invalid characters in input'); return; } // Handle decimals if (strpos($int, '.') !== false) { $decimal = substr($int, strpos($int, '.') + 1); $int = substr($int, 0, strpos($int, '.')); } // Lose insignificant zeros $int = ltrim($int, '0'); // Check for valid number if ($int == '') { $int = '0'; } // Lose the negative, don't use abs() so as to allow large numbers if ($negative = ($int < 0)) { $int = substr($int, 1); } // Number too big? if (strlen($int) > 18) { //throw new Exception('Out of range'); echo('Out of range'); return; } // Keep original number $orig = $int; /** * Main number deciphering bit thing */ switch (strlen($int)) { // Single digit number case '1': $text = $this->units[$int]; break; // Two digit number case '2': if ($int{0} == '1') { $text = $this->teens[$int{1}]; } else if ($int{1} == '0') { $text = $this->tens[$int{0}]; } else { $text = $this->tens[$int{0}] . '-' . $this->units[$int{1}]; } break; // Three digit number case '3': if ($int % 100 == 0) { $text = $this->units[$int{0}] . ' hundred'; } else { $text = $this->units[$int{0}] . ' hundred and ' . $this->GetText(substr($int, 1)); } break; // Anything else default: $pieces = array(); $suffixIndex = 0; // Handle the last three digits $num = substr($int, -3); if ($num > 0) { $pieces[] = $this->GetText($num); } $int = substr($int, 0, -3); // Now handle the thousands/millions etc while (strlen($int) > 3) { $num = substr($int, -3); if ($num > 0) { $pieces[] = $this->GetText($num) . ' ' . $this->suffix[$suffixIndex]; } $int = substr($int, 0, -3); $suffixIndex++; } $pieces[] = $this->GetText(substr($int, -3)) . ' ' . $this->suffix[$suffixIndex]; /** * Figure out whether we need to add "and" in there somewhere */ $pieces = array_reverse($pieces); if (count($pieces) > 1 AND strpos($pieces[count($pieces) - 1], ' and ') === false) { $pieces[] = $pieces[count($pieces) - 1]; $pieces[count($pieces) - 2] = 'and'; } // Create the text $text = implode(' ', $pieces); // Negative number? if ($negative) { $text = 'minus ' . $text; } break; } /** * Handle any decimal part */ if (!empty($decimal)) { $pieces = array(); $decimal = preg_replace('#[^0-9]#', '', $decimal); for ($i=0, $len=strlen($decimal); $i<$len; ++$i) { $pieces[] = $this->units[$decimal{$i}]; } $text .= ' point ' . implode(' ', $pieces); } return $text; } /** * Returns text for given number. Parameter should ideally * be a string (to handle large numbers) though integers are * OK. * * @param string $int Number to convert * @return string Resulting textual representation */ function GetText($int) { return $this->ToString($int); } /** * Returns text and number for a randomly generated number. * * @return array Array of number and textual representation */ function Get() { $int = mt_rand(1, 99999); return array($int, $this->ToString($int)); } /** * Returns currency version of a given number. * * @param string $int Number to convert * @param string $major Word to use for left hand side of decimal point * @param string $minor Word to use for right hand side of decimal point * @return string Resulting string */ function GetCurrency($int, $major = 'pound', $minor = 'pence') { if (strpos($int, '.') !== false) { $left = substr($int, 0, strpos($int, '.')); $right = substr($int, strpos($int, '.') + 1); // Plural $major ? if ((int)abs($left) != 1) { $major .= 's'; } $text = $this->GetText($left) . " $major and " . $this->GetText($right) . " $minor"; } else { $text = $this->GetText($int) . " $major"; } return $text; } } ?>