3v4l.org

run code in 300+ PHP versions simultaneously
<?php $n2w = new NumberToWords(); // not in use var_dump($n2w->convertToWords($amount)); class NumberToWords { // base 10 dictionary private $dictionary = array( 0 => 'zero', 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7 => 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten', 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen', 14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen', 18 => 'eighteen', 19 => 'nineteen', 20 => 'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety', 100 => 'hundred', 1000 => 'thousand', 1000000 => 'million', 1000000000 => 'billion', 1000000000000 => 'trillion', 1000000000000000 => 'quadrillion', 1000000000000000000 => 'quintillion' ); // irregular ordinals private $ordinal_dictionary = array( 0 => 'zeroth', 1 => 'first', 2 => 'second', 3 => 'third', 5 => 'fifth', 8 => 'eighth', 12 => 'twelfth', 20 => 'twentieth', 30 => 'thirtieth', 40 => 'fourtieth', 50 => 'fiftieth', 60 => 'sixtieth', 70 => 'seventieth', 80 => 'eightieth', 90 => 'ninetieth', 100 => 'hundredth', 1000 => 'thousandth', 1000000 => 'millionth', 1000000000 => 'billionth', 1000000000000 => 'trillionth', 1000000000000000 => 'quadrillionth', 1000000000000000000 => 'quintillionth' ); // math dictionary (not currently in use) private $math_dictionary = array( '+' => 'add', '-' => 'subtract', '/' => 'divide', '*' => 'multiply', '%' => 'modulus', '>' => 'greater than', '<' => 'less than', '=' => 'equal' ); public $hyphen = '-'; public $conjunction = 'and'; public $separator = ','; public $negative = 'negative '; // or minus public $decimal = 'point'; public $percent = 'percent'; public $degrees = 'degree'; public $currency_type = 'dollar'; public $currency_fraction_type = 'cent'; public $uppercase_words = TRUE; // will uc words except 'and' public $include_zero_dollars = TRUE; public $include_zero_cents = TRUE; const AUTOMATIC_MODE = 'automatic_mode'; const CURRENCY_MODE = 'currency_mode'; private $mode; /** * Constructor */ public function __construct() { $this->mode = self::AUTOMATIC_MODE; } /** * Sets the mode used during conversion * * @param string $mode */ public function setMode($mode) { $this->mode = $mode; } /** * Converts any number to words * * @param float $number * @param string $mode * (optional) * @return string */ public function convertToWords($number, $mode = null) { if ($mode != null) $this->mode = $mode; // default vars to null $is_negative = FALSE; $string = $fraction = null; $unit_type = ''; $support_plural_units = TRUE; // must be numeric if (!is_numeric($number)){ // strip chars that make this non-numeric // auto-detect currency and set mode (if at beginning of string) if (strpos($number, '$') == 0){ $this->mode = self::CURRENCY_MODE; } // handle simple percent (if at end of string) if (strpos($number, '%') == strlen($number) - 1){ $this->mode = self::AUTOMATIC_MODE; $unit_type .= $this->percent; $support_plural_units = FALSE; } // handle simple degrees (if at end of string) if (strpos($number, '°') == strlen($number) - 1){ $this->mode = self::AUTOMATIC_MODE; $unit_type .= $this->degrees; } // clean %, $, �, comma (,) $number = preg_replace('/[,\%\$°]/', '', $number); // if it's not clean now, it's not something we can handle if (!is_numeric($number)){ return false; } } // buffer overflow check if (($number >= 0 && (int)$number < 0) || (int)$number < 0 - PHP_INT_MAX){ trigger_error('convert only accepts numbers between -' . PHP_INT_MAX . ' and ' . PHP_INT_MAX, E_USER_WARNING); return false; } // check for negative number, if so store/remove negative and continue if ($number < 0){ $is_negative = TRUE; $number = abs($number); } if ($this->mode == self::CURRENCY_MODE){ if ($number == (int)$number){ $number .= '.00'; // force decimal by string } } // check for fraction, store it for later if (strpos($number, '.') !== FALSE){ // only apply rounding if we have a fraction if ($this->mode == self::CURRENCY_MODE && $number != (int)$number){ $number = round($number, 2); // we want .109 to round to .11 cents } list($number, $fraction) = explode('.', $number); if ($this->mode == self::CURRENCY_MODE && $fraction != null){ if (strlen($fraction) == 1){ $fraction *= 10; // we want .1 to become .10 (or 10 cents) } } } // if dealing in currency, add units (Dollars) if ($number != 0 || ($this->include_zero_dollars && $number == 0)){ $string .= $this->convert($number); // add units in currency mode if ($this->mode == self::CURRENCY_MODE){ $string .= ' ' . $this->currency_type . ($number != 1 ? 's' : '') . ''; } } // handle fraction if ($fraction !== null && is_numeric($fraction)){ if ($this->mode == self::CURRENCY_MODE){ // change mode to default so there is no unit type if (($fraction == 0 && $this->include_zero_cents) || $fraction != 0){ $before_mode = $this->mode; $this->mode = self::AUTOMATIC_MODE; // if string is not null, we want to add 'and' if ($string != null) $string .= " " . $this->conjunction . " "; $string .= $this->convert($fraction); $this->mode = $before_mode; // restore previous mode $string .= ' ' . $this->currency_fraction_type . ($fraction != 1 ? 's' : ''); } if ($this->uppercase_words) $string = $this->ucwords($string); return $string; } if ($this->mode == self::AUTOMATIC_MODE){ $string .= " " . $this->decimal . " "; // just output 'point' } $words = array(); foreach(str_split((string)$fraction) as $number ){ $words[] = $this->dictionary[$number]; } $string .= implode(' ', $words); } // handle units, if required if ($unit_type != '' && $support_plural_units && ($number != 1 || $fraction != null)) $unit_type .= 's'; // apply last minute formatting $string = ($is_negative ? $this->negative : '') . $string . " " . $unit_type; // uppercase words if set if ($this->uppercase_words) $string = $this->ucwords($string); return trim($string); } /** * Print out date/time related words * * @param string $date * @param string $pattern * @return string */ public function convertDateToWords($date, $pattern = 'l, F jS, Y') { // get the time $time = strtotime($date); // adjust the pattern for testing adding non-interpreted characters // $pattern = "l, F \u jS, Y \h"; $parts = preg_split('//', $pattern); $good_parts = array(); for($i = 0; $i < count($parts); $i++){ $part = $parts[$i]; if ($part == "\\"){ // this is an escaped character, get the character that follows as part $part = $parts[++$i]; // get next item as assignment } else{ // track 'S' (st, nd, rd, th suffix), we need the item before (if item exists and is a number) // make it read first, second, third, fourth, fifth, sixth, seventh, eighth, nineth, tenth, eleventh, twelveth... if ($part == 'S' && $i > 0){ $prev_val = date($parts[$i - 1], $time); if (is_numeric($prev_val)){ // numbers with different rules $part = $this->getNumberOrdinal($prev_val); array_pop($good_parts); // remove last item $good_parts[] = $part; // add this item continue; } } if (trim($part) != '' && $part != ',' && ($value = date($part, $time)) !== FALSE){ if ($value != ''){ // we have an equated value if (is_numeric($value)){ // this a number, let's convert it to text $good_parts[] = trim($this->convertToWords($value, self::AUTOMATIC_MODE)); } else{ // this is not a number, we don't alter it $good_parts[] = $value; } } continue; } } $good_parts[] = $part; } // echo var_export($good_parts, TRUE)."\n"; return trim(implode('', $good_parts)); } /** * Converts a number into the word-ordinal form * * @param int $number * @return string */ public function getNumberOrdinal($number) { $number = (int)abs($number); // cannot have fractions or be negative // check if number given is in ordinal dictionary if (array_key_exists($number, $this->ordinal_dictionary)){ // simple lookup in dictionary $ord = $this->ordinal_dictionary[$number]; } else{ // first remove all but the last two digits $n1 = $number % 100; // remove all but last digit unless the number is in the teens, which all should be 'th' $n2 = ($n1 < 20 ? $number : $number % 10); // check if digit less than 20 is in dictionary if (array_key_exists($n2, $this->ordinal_dictionary)){ $ord = $this->ordinal_dictionary[$n2]; if ($number > 20){ $words = $this->convertToWords($number); // we need to account for a two-part number $word_list = explode('-', $words); $word_list[count($word_list) - 1] = $ord; $ord = implode('-', $word_list); } } else{ // if not zero, use number straight across if ($n2 != 0){ $ord = $this->convert($number) . 'th'; } } } // apply this to finished product, not ord if ($this->uppercase_words) $ord = $this->ucwords($ord); return $ord; } /** * Helper method to access converting almost all words to ucfirst * * @param string $string * @return string */ private function ucwords($string) { return preg_replace_callback("/[a-zA-Z-]+/", array( &$this, 'limitedUcwords' ), $string); } /** * Called by preg callback * * @param string $match * @return string */ private function limitedUcwords($match) { $exclude = array( 'and' ); // list of words to not ucfirst if (in_array(strtolower($match[0]), $exclude)) return $match[0]; return ucfirst($match[0]); } /** * Converts a number to words regardless of other formatting * * @param int $number * @return boolean */ private function convert($number) { $string = ''; $number = (int)$number; // must be a whole number (no fraction, no strings) switch (true){ case $number < 21: $string = $this->dictionary[$number]; break; case $number < 100: $tens = ((int)($number / 10)) * 10; $units = $number % 10; $string = $this->dictionary[$tens]; if ($units){ $string .= $this->hyphen . $this->dictionary[$units]; } break; case $number < 1000: $hundreds = $number / 100; $remainder = $number % 100; $string = $this->dictionary[$hundreds] . ' ' . $this->dictionary[100]; if ($remainder){ $string .= " " . $this->conjunction . " " . $this->convert($remainder); } break; default: $baseUnit = pow(1000, floor(log($number, 1000))); $numBaseUnits = (int)($number / $baseUnit); $remainder = $number % $baseUnit; $string = $this->convert($numBaseUnits) . ' ' . $this->dictionary[$baseUnit]; if ($remainder){ $string .= $remainder < 100 ? " " . $this->conjunction . " " : $this->separator . " "; $string .= $this->convert($remainder); } break; } return $string; } }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0150.00018.60
8.3.50.0170.00622.96
8.3.40.0160.00319.27
8.3.30.0120.00319.21
8.3.20.0040.00420.49
8.3.10.0060.00321.94
8.3.00.0040.00417.88
8.2.180.0160.00617.13
8.2.170.0150.00022.96
8.2.160.0110.00320.65
8.2.150.0040.00424.18
8.2.140.0080.00024.66
8.2.130.0030.00526.16
8.2.120.0000.00820.98
8.2.110.0100.00022.20
8.2.100.0090.00318.09
8.2.90.0050.00319.34
8.2.80.0030.00517.97
8.2.70.0080.00417.98
8.2.60.0000.00817.93
8.2.50.0090.00018.07
8.2.40.0000.00818.22
8.2.30.0080.00018.21
8.2.20.0000.00818.05
8.2.10.0040.00418.27
8.2.00.0030.00618.17
8.1.280.0080.00825.92
8.1.270.0050.00324.02
8.1.260.0080.00026.35
8.1.250.0030.00628.09
8.1.240.0070.00323.96
8.1.230.0030.00919.29
8.1.220.0050.00317.91
8.1.210.0000.00818.77
8.1.200.0040.00417.60
8.1.190.0030.00617.60
8.1.180.0000.00918.10
8.1.170.0080.00018.84
8.1.160.0000.00822.27
8.1.150.0000.00819.10
8.1.140.0050.00317.76
8.1.130.0000.00717.87
8.1.120.0000.00817.75
8.1.110.0060.00317.71
8.1.100.0060.00317.80
8.1.90.0040.00417.66
8.1.80.0000.00717.82
8.1.70.0040.00417.64
8.1.60.0060.00317.83
8.1.50.0030.00617.78
8.1.40.0060.00317.83
8.1.30.0000.00817.94
8.1.20.0040.00417.84
8.1.10.0080.00017.80
8.1.00.0040.00417.79
8.0.300.0000.00718.77
8.0.290.0040.00417.25
8.0.280.0050.00218.52
8.0.270.0040.00417.42
8.0.260.0040.00417.42
8.0.250.0000.00717.36
8.0.240.0000.00717.29
8.0.230.0070.00017.29
8.0.220.0040.00417.28
8.0.210.0050.00317.27
8.0.200.0070.00017.30
8.0.190.0000.00817.32
8.0.180.0070.00017.30
8.0.170.0030.00617.29
8.0.160.0030.00517.17
8.0.150.0040.00417.15
8.0.140.0000.00717.20
8.0.130.0030.00313.70
8.0.120.0050.00317.26
8.0.110.0040.00417.22
8.0.100.0030.00517.23
8.0.90.0000.00717.31
8.0.80.0150.00617.17
8.0.70.0000.00917.27
8.0.60.0040.00417.29
8.0.50.0000.00817.03
8.0.30.0170.00917.43
8.0.20.0080.01417.40
8.0.10.0050.00317.38
8.0.00.0080.01016.98
7.4.330.0050.00015.00
7.4.320.0050.00216.86
7.4.300.0000.00817.02
7.4.290.0070.00017.01
7.4.280.0040.00416.86
7.4.270.0000.00716.82
7.4.260.0030.00616.94
7.4.250.0030.00516.83
7.4.240.0040.00316.89
7.4.230.0000.00716.94
7.4.220.0120.00616.85
7.4.210.0060.00916.98
7.4.200.0000.00816.99
7.4.160.0170.00817.04
7.4.150.0160.00817.40
7.4.140.0110.00817.86
7.4.130.0120.00816.83
7.4.120.0090.01016.89
7.4.110.0140.00416.76
7.4.100.0150.00616.88
7.4.90.0080.01116.89
7.4.80.0090.00919.39
7.4.70.0100.00916.74
7.4.60.0100.01016.98
7.4.50.0000.00916.93
7.4.40.0070.01016.77
7.4.30.0090.00916.82
7.4.00.0030.01214.96
7.3.330.0030.00313.59
7.3.320.0060.00013.72
7.3.310.0020.00516.63
7.3.300.0020.00516.60
7.3.290.0060.00916.73
7.3.280.0080.01216.75
7.3.270.0090.00917.40
7.3.260.0030.01416.76
7.3.250.0080.01116.87
7.3.240.0100.00716.79
7.3.230.0060.01317.02
7.3.210.0140.00316.74
7.3.200.0080.00919.39
7.3.190.0110.00616.96
7.3.180.0060.01116.81
7.3.170.0190.00916.65
7.3.160.0100.01016.78
7.3.10.0000.01416.95
7.3.00.0030.00616.60
7.2.330.0120.00616.91
7.2.320.0030.01917.01
7.2.310.0170.00317.02
7.2.300.0040.02216.96
7.2.290.0110.00616.99
7.2.130.0070.00717.17
7.2.120.0090.00316.84
7.2.110.0060.00316.92
7.2.100.0040.00716.91
7.2.90.0000.01217.19
7.2.80.0000.01217.15
7.2.70.0060.00616.90
7.2.60.0080.00417.00
7.2.50.0060.00617.17
7.2.40.0060.00917.23
7.2.30.0030.01317.20
7.2.20.0030.00616.91
7.2.10.0090.00617.20
7.2.00.0030.01118.44
7.1.250.0060.00315.93
7.1.100.0030.00618.56
7.1.70.0000.00717.31
7.1.60.0000.02619.40
7.1.50.0280.01334.91
7.1.00.0100.07022.35
7.0.200.0030.00616.88
7.0.140.0070.07322.05
7.0.110.0000.04020.12
7.0.100.0100.03720.16
7.0.90.0200.02320.23
7.0.80.0130.07720.21
7.0.70.0100.05320.11
7.0.60.0000.06020.10
7.0.50.0100.07320.03
7.0.40.0100.07319.75
7.0.30.0030.08719.70
7.0.20.0130.07319.70
7.0.10.0030.07319.75
7.0.00.0000.08719.84
5.6.280.0100.07021.17
5.6.260.0070.05020.67
5.6.250.0170.07020.77
5.6.240.0100.06020.94
5.6.230.0170.07320.63
5.6.220.0030.04020.76
5.6.210.0130.07320.69
5.6.200.0070.07320.74
5.6.190.0030.08320.76
5.6.180.0070.03320.67
5.6.170.0030.07720.64
5.6.160.0000.09020.64
5.6.150.0070.06320.69
5.6.140.0070.08320.73
5.6.130.0070.03320.67
5.6.120.0100.07720.54
5.6.110.0030.03720.53
5.6.100.0030.08020.72
5.6.90.0100.08020.72
5.6.80.0000.04020.10
5.6.70.0000.08320.04
5.6.60.0070.03020.01
5.6.50.0070.07320.10
5.6.40.0030.08320.14
5.6.30.0070.03720.07
5.6.20.0000.08719.99
5.6.10.0100.07320.09
5.6.00.0070.07720.07
5.5.380.0130.07017.64
5.5.370.0000.08717.78
5.5.360.0100.06717.60
5.5.350.0030.08017.71
5.5.340.0070.08018.29
5.5.330.0030.03718.07
5.5.320.0030.08718.21
5.5.310.0170.07318.23
5.5.300.0030.09018.14
5.5.290.0070.08318.17
5.5.280.0070.05718.02
5.5.270.0030.05718.26
5.5.260.0070.08018.01
5.5.250.0030.08017.88
5.5.240.0030.03717.64
5.5.230.0000.08317.45
5.5.220.0200.06317.52
5.5.210.0030.07017.39
5.5.200.0130.02317.38
5.5.190.0030.03717.38
5.5.180.0000.04317.37
5.5.160.0030.03317.61
5.5.150.0030.03317.37
5.5.140.0070.04317.45
5.5.130.0030.04017.51
5.5.120.0000.04017.61
5.5.110.0100.07317.56
5.5.100.0000.04317.40
5.5.90.0030.06317.26
5.5.80.0000.05017.39
5.5.70.0070.03317.28
5.5.60.0000.03717.38
5.5.50.0170.07017.53
5.5.40.0070.07717.50
5.5.30.0030.05717.38
5.5.20.0070.07317.49
5.5.10.0030.03717.30
5.5.00.0030.03717.46
5.4.450.0130.05319.31
5.4.440.0100.02719.71
5.4.430.0100.07719.35
5.4.420.0030.08319.56
5.4.410.0030.08319.53
5.4.400.0070.03319.04
5.4.390.0030.07719.22
5.4.380.0030.03319.14
5.4.370.0070.04719.14
5.4.360.0030.05319.01
5.4.350.0000.04719.03
5.4.340.0030.04019.02
5.4.320.0100.06719.02
5.4.310.0070.06019.25
5.4.300.0130.06319.06
5.4.290.0070.07019.03
5.4.280.0030.03719.10
5.4.270.0000.06719.16
5.4.260.0070.07019.17
5.4.250.0070.04719.22
5.4.240.0070.03319.03
5.4.230.0000.05319.37
5.4.220.0170.06719.14
5.4.210.0030.07319.21
5.4.200.0000.08319.24
5.4.190.0130.02319.00
5.4.180.0030.06019.01
5.4.170.0030.04019.21
5.4.160.0100.03019.15
5.4.150.0070.03319.04
5.4.140.0070.07316.69
5.4.130.0000.03716.43
5.4.120.0070.06316.43
5.4.110.0130.05716.53
5.4.100.0030.03316.44
5.4.90.0030.06316.61
5.4.80.0030.04316.59
5.4.70.0000.07716.49
5.4.60.0030.07016.58
5.4.50.0200.05316.60
5.4.40.0030.07716.57
5.4.30.0030.07316.49
5.4.20.0030.07016.39
5.4.10.0030.07016.59
5.4.00.0070.07715.87

preferences:
51.64 ms | 401 KiB | 5 Q