Is there any native function, or other practical way, to take a number in float
and convert it to the extended number?
Example:
//input: 2.000,00
//output: dois mil
Is there any native function, or other practical way, to take a number in float
and convert it to the extended number?
Example:
//input: 2.000,00
//output: dois mil
Native function does not exist, but there goes a recursive implementation.
<?php
function convert_number_to_words($number) {
$hyphen = '-';
$conjunction = ' e ';
$separator = ', ';
$negative = 'menos ';
$decimal = ' ponto ';
$dictionary = array(
0 => 'zero',
1 => 'um',
2 => 'dois',
3 => 'três',
4 => 'quatro',
5 => 'cinco',
6 => 'seis',
7 => 'sete',
8 => 'oito',
9 => 'nove',
10 => 'dez',
11 => 'onze',
12 => 'doze',
13 => 'treze',
14 => 'quatorze',
15 => 'quinze',
16 => 'dezesseis',
17 => 'dezessete',
18 => 'dezoito',
19 => 'dezenove',
20 => 'vinte',
30 => 'trinta',
40 => 'quarenta',
50 => 'cinquenta',
60 => 'sessenta',
70 => 'setenta',
80 => 'oitenta',
90 => 'noventa',
100 => 'cento',
200 => 'duzentos',
300 => 'trezentos',
400 => 'quatrocentos',
500 => 'quinhentos',
600 => 'seiscentos',
700 => 'setecentos',
800 => 'oitocentos',
900 => 'novecentos',
1000 => 'mil',
1000000 => array('milhão', 'milhões'),
1000000000 => array('bilhão', 'bilhões'),
1000000000000 => array('trilhão', 'trilhões'),
1000000000000000 => array('quatrilhão', 'quatrilhões'),
1000000000000000000 => array('quinquilhão', 'quinquilhões')
);
if (!is_numeric($number)) {
return false;
}
if (($number >= 0 && (int) $number < 0) || (int) $number < 0 - PHP_INT_MAX) {
// overflow
trigger_error(
'convert_number_to_words só aceita números entre ' . PHP_INT_MAX . ' à ' . PHP_INT_MAX,
E_USER_WARNING
);
return false;
}
if ($number < 0) {
return $negative . convert_number_to_words(abs($number));
}
$string = $fraction = null;
if (strpos($number, '.') !== false) {
list($number, $fraction) = explode('.', $number);
}
switch (true) {
case $number < 21:
$string = $dictionary[$number];
break;
case $number < 100:
$tens = ((int) ($number / 10)) * 10;
$units = $number % 10;
$string = $dictionary[$tens];
if ($units) {
$string .= $conjunction . $dictionary[$units];
}
break;
case $number < 1000:
$hundreds = floor($number / 100)*100;
$remainder = $number % 100;
$string = $dictionary[$hundreds];
if ($remainder) {
$string .= $conjunction . convert_number_to_words($remainder);
}
break;
default:
$baseUnit = pow(1000, floor(log($number, 1000)));
$numBaseUnits = (int) ($number / $baseUnit);
$remainder = $number % $baseUnit;
if ($baseUnit == 1000) {
$string = convert_number_to_words($numBaseUnits) . ' ' . $dictionary[1000];
} elseif ($numBaseUnits == 1) {
$string = convert_number_to_words($numBaseUnits) . ' ' . $dictionary[$baseUnit][0];
} else {
$string = convert_number_to_words($numBaseUnits) . ' ' . $dictionary[$baseUnit][1];
}
if ($remainder) {
$string .= $remainder < 100 ? $conjunction : $separator;
$string .= convert_number_to_words($remainder);
}
break;
}
if (null !== $fraction && is_numeric($fraction)) {
$string .= $decimal;
$words = array();
foreach (str_split((string) $fraction) as $number) {
$words[] = $dictionary[$number];
}
$string .= implode(' ', $words);
}
return $string;
}
echo '<pre>';
echo "123456789\n";
echo convert_number_to_words(123456789);
echo "\n\n";
echo "123456789.123\n";
echo convert_number_to_words(123456789.123);
echo "\n\n";
echo "-1922685.477\n";
echo convert_number_to_words(-1922685.477);
echo "\n\n";
echo "123456789123.12345\n";
echo convert_number_to_words(123456789123.12345); // rounds the fractional part
echo "\n\n";
echo "123456789123.12345\n";
echo convert_number_to_words('123456789123.12345'); // does not round
echo '</pre>';
Adapted function of link
There is no native function of php for this, even because it would require an i18n to be able to describe extensively values of other languages, I believe the most advisable in this case is to use a class for this in ExtremoConhecimento has a function that solves this problem.
Example:
class Monetary {
private static $unidades = array("um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez", "onze", "doze",
"treze", "quatorze", "quinze", "dezesseis", "dezessete", "dezoito", "dezenove");
private static $dezenas = array("dez", "vinte", "trinta", "quarenta", "cinqüenta", "sessenta", "setenta", "oitenta", "noventa");
private static $centenas = array("cem", "duzentos", "trezentos", "quatrocentos", "quinhentos",
"seiscentos", "setecentos", "oitocentos", "novecentos");
private static $milhares = array(
array("text" => "mil", "start" => 1000, "end" => 999999, "div" => 1000),
array("text" => "milhão", "start" => 1000000, "end" => 1999999, "div" => 1000000),
array("text" => "milhões", "start" => 2000000, "end" => 999999999, "div" => 1000000),
array("text" => "bilhão", "start" => 1000000000, "end" => 1999999999, "div" => 1000000000),
array("text" => "bilhões", "start" => 2000000000, "end" => 2147483647, "div" => 1000000000)
);
const MIN = 0.01;
const MAX = 2147483647.99;
const MOEDA = " real ";
const MOEDAS = " reais ";
const CENTAVO = " centavo ";
const CENTAVOS = " centavos ";
static
function numberToExt($number, $moeda = true) {
if ($number >= self::MIN && $number <= self::MAX) {
$value = self::conversionR((int) $number);
if ($moeda) {
if (floor($number) == 1) {
$value. = self::MOEDA;
} else if (floor($number) > 1)
$value. = self::MOEDAS;
}
$decimals = self::extractDecimals($number);
if ($decimals > 0.00) {
$decimals = round($decimals * 100);
$value. = " e ".self::conversionR($decimals);
if ($moeda) {
if ($decimals == 1) {
$value. = self::CENTAVO;
} else if ($decimals > 1)
$value. = self::CENTAVOS;
}
}
}
return trim($value);
}
private static
function extractDecimals($number) {
return $number - floor($number);
}
static
function conversionR($number) {
if (in_array($number, range(1, 19))) {
$value = self::$unidades[$number - 1];
} else if (in_array($number, range(20, 90, 10))) {
$value = self::$dezenas[floor($number / 10) - 1].
" ";
} else if (in_array($number, range(21, 99))) {
$value = self::$dezenas[floor($number / 10) - 1].
" e ".self::conversionR($number % 10);
} else if (in_array($number, range(100, 900, 100))) {
$value = self::$centenas[floor($number / 100) - 1].
" ";
} else if (in_array($number, range(101, 199))) {
$value = ' cento e '.self::conversionR($number % 100);
} else if (in_array($number, range(201, 999))) {
$value = self::$centenas[floor($number / 100) - 1].
" e ".self::conversionR($number % 100);
} else {
foreach(self::$milhares as $item) {
if ($number >= $item['start'] && $number <= $item['end']) {
$value = self::conversionR(floor($number / $item['div'])).
" ".$item['text'].
" ".self::conversionR($number % $item['div']);
break;
}
}
}
return $value;
}
}
echo Monetary::numberToExt(500.00);
Entry:
echo Monetary::numberToExt(500.00);
Output:
quinhentos reais
Source: link
This was the best function I found. You can test with all possible values, if you find an error, let me know.
function extenso($valor = 0, $maiusculas = false) {
if(!$maiusculas){
$singular = ["centavo", "real", "mil", "milhão", "bilhão", "trilhão", "quatrilhão"];
$plural = ["centavos", "reais", "mil", "milhões", "bilhões", "trilhões", "quatrilhões"];
$u = ["", "um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove"];
}else{
$singular = ["CENTAVO", "REAL", "MIL", "MILHÃO", "BILHÃO", "TRILHÃO", "QUADRILHÃO"];
$plural = ["CENTAVOS", "REAIS", "MIL", "MILHÕES", "BILHÕES", "TRILHÕES", "QUADRILHÕES"];
$u = ["", "um", "dois", "TRÊS", "quatro", "cinco", "seis", "sete", "oito", "nove"];
}
$c = ["", "cem", "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos", "setecentos", "oitocentos", "novecentos"];
$d = ["", "dez", "vinte", "trinta", "quarenta", "cinquenta", "sessenta", "setenta", "oitenta", "noventa"];
$d10 = ["dez", "onze", "doze", "treze", "quatorze", "quinze", "dezesseis", "dezesete", "dezoito", "dezenove"];
$z = 0;
$rt = "";
$valor = number_format($valor, 2, ".", ".");
$inteiro = explode(".", $valor);
for($i=0;$i<count($inteiro);$i++)
for($ii=strlen($inteiro[$i]);$ii<3;$ii++)
$inteiro[$i] = "0".$inteiro[$i];
$fim = count($inteiro) - ($inteiro[count($inteiro)-1] > 0 ? 1 : 2);
for ($i=0;$i<count($inteiro);$i++) {
$valor = $inteiro[$i];
$rc = (($valor > 100) && ($valor < 200)) ? "cento" : $c[$valor[0]];
$rd = ($valor[1] < 2) ? "" : $d[$valor[1]];
$ru = ($valor > 0) ? (($valor[1] == 1) ? $d10[$valor[2]] : $u[$valor[2]]) : "";
$r = $rc.(($rc && ($rd || $ru)) ? " e " : "").$rd.(($rd &&
$ru) ? " e " : "").$ru;
$t = count($inteiro)-1-$i;
$r .= $r ? " ".($valor > 1 ? $plural[$t] : $singular[$t]) : "";
if ($valor == "000")$z++; elseif ($z > 0) $z--;
if (($t==1) && ($z>0) && ($inteiro[0] > 0)) $r .= (($z>1) ? " de " : "").$plural[$t];
if ($r) $rt = $rt . ((($i > 0) && ($i <= $fim) && ($inteiro[0] > 0) && ($z < 1)) ? ( ($i < $fim) ? ", " : " e ") : " ") . $r;
}
if(!$maiusculas){
$return = $rt ? $rt : "zero";
} else {
if ($rt) $rt = ereg_replace(" E "," e ",ucwords($rt));
$return = ($rt) ? ($rt) : "Zero" ;
}
if(!$maiusculas){
return ereg_replace(" E "," e ",ucwords($return));
}else{
return strtoupper($return);
}
}
Example:
$valor = 405.63;
$dim = extenso($valor);
$valor = number_format($valor, 2, ",", ".");
echo "R$ ".$valor." = ".$dim;
Output
R $ 405.63 = Four Hundred and Five Reais and Sixty-three Centavos
But if you just need something simple and have control of the input values, try this:
function numero_extenso($numero=0){
if($numero){
$dicionario = array(
1 => 'um',
2 => 'dois',
3 => 'três',
4 => 'quatro',
5 => 'cinco',
6 => 'seis',
7 => 'sete',
8 => 'oito',
9 => 'nove',
10 => 'dez',
11 => 'onze',
12 => 'doze',
13 => 'treze',
14 => 'quatorze',
15 => 'quinze',
16 => 'dezesseis',
17 => 'dezessete',
18 => 'dezoito',
19 => 'dezenove',
20 => 'vinte',
30 => 'trinta',
40 => 'quarenta',
50 => 'cinquenta',
100 => 'cento');
return $dicionario[$numero];
}
}