Skip to content

Instantly share code, notes, and snippets.

@Chrispassold
Created July 9, 2020 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chrispassold/4151ed74132d25e6e4ec946e3193c97c to your computer and use it in GitHub Desktop.
Save Chrispassold/4151ed74132d25e6e4ec946e3193c97c to your computer and use it in GitHub Desktop.
Brazilian number converter to string
import java.math.BigDecimal
import java.security.InvalidParameterException
import kotlin.text.StringBuilder
object BrazilianNumberStringConverter {
private val units = arrayOf(
"",
"um",
"dois",
"três",
"quatro",
"cinco",
"seis",
"sete",
"oito",
"nove",
"dez",
"onze",
"doze",
"treze",
"quatorze",
"quinze",
"dezesseis",
"dezessete",
"dezoito",
"dezenove"
)
private val dozens = arrayOf(
"",
"",
"vinte",
"trinta",
"quarenta",
"cinquenta",
"sessenta",
"setenta",
"oitenta",
"noventa"
)
private val hundreds = arrayOf(
"cem",
"cento",
"duzentos",
"trezentos",
"quatrocentos",
"quinhentos",
"seiscentos",
"setecentos",
"oitocentos",
"novecentos"
)
private fun BigDecimal.minus(double: Double) = this.minus(BigDecimal.valueOf(double))
private fun BigDecimal.divideAndGetIntegerPart(double: Double) =
this.divide(BigDecimal.valueOf(double)).toBigInteger().toInt()
private data class NumberMap(
var millions: Int = 0,
var thousands: Int = 0,
var hundreds: Int = 0
) {
private fun millions() = millions * 1000000
private fun thousands() = thousands * 1000
private fun hundreds() = hundreds
fun asInt(): Int {
return millions() + thousands() + hundreds()
}
override fun toString(): String {
return "Number(millions=$millions, thousands=$thousands, hundreds=$hundreds)"
}
}
private fun assertMaximmumValue(number: Int) {
if (number.toString().length > 9)
throw InvalidParameterException("Maximmum number is 999 millions")
}
private fun mapNumber(number: Int): NumberMap {
var value = number
val result = NumberMap()
// verifica quantos milhoes tem
result.millions = value / 1000000
value = value.minus(result.millions * 1000000)
// verifica quantos milhares tem
result.thousands = value / 1000
value = value.minus(result.thousands * 1000)
// verifica quantas centenas tem
result.hundreds = value
return result
}
private fun mapNumber(number: BigDecimal): NumberMap {
var value: BigDecimal = number.setScale(2, BigDecimal.ROUND_HALF_EVEN)
val result = NumberMap()
if (number <= BigDecimal.ZERO)
return result
// verifica quantos milhoes tem
result.millions = value.divideAndGetIntegerPart(1000000.0)
value = value.minus(result.millions * 1000000.0)
// verifica quantos milhares tem
result.thousands = value.divideAndGetIntegerPart(1000.0)
value = value.minus(result.thousands * 1000.0)
// verifica quantas centenas tem
result.hundreds = value.divideAndGetIntegerPart(1.0)
return result
}
private fun mapDecimalNumber(number: BigDecimal): NumberMap {
val decimals = number.remainder(BigDecimal.ONE).multiply(BigDecimal.valueOf(100.0))
return mapNumber(decimals)
}
private fun formatDozenPart(number: Int): String {
val sb = StringBuilder()
if (number < 20) {
sb.append(units[number])
} else {
val dozenPart = number / 10
val unitPart = number % 10
sb.append(dozens[dozenPart])
if (unitPart > 0)
sb.append(" e ").append(units[unitPart])
}
return sb.toString()
}
private fun formatHundredPart(number: Int): String {
val sb = StringBuilder()
if (number == 100)
return hundreds[0]
val hundredPart = number / 100
val dozenPart = number % 100
if (hundredPart > 0)
sb.append(hundreds[hundredPart]).append(if (dozenPart > 0) " e " else "")
if (dozenPart > 0)
sb.append(formatDozenPart(dozenPart))
return sb.toString()
}
private fun formatQualifier(number: Int): String {
val sb = StringBuilder()
assertMaximmumValue(number)
val numberString = number.toString()
val numberObject = mapNumber(number)
when {
numberString.length > 6 -> {
// millions
sb.append(getStringNumber(numberObject.millions))
.append(if (numberObject.millions > 1) " milhões " else " milhão ")
sb.append(getStringNumber(numberObject.thousands)).append(" mil ")
sb.append(getStringNumber(numberObject.hundreds))
}
numberString.length > 3 -> {
// thousands
sb.append(getStringNumber(numberObject.thousands)).append(" mil ")
sb.append(getStringNumber(numberObject.hundreds))
}
else -> {
// hundreds
sb.append(formatHundredPart(numberObject.hundreds))
}
}
return sb.toString()
}
private fun getStringNumber(number: Int): String {
return formatQualifier(number)
}
fun convertToString(number: Int): String {
if (number < 0) return "0"
return getStringNumber(number)
}
fun convertToStringCurrency(number: BigDecimal): String {
val numbers = mapNumber(number)
val decimals = mapDecimalNumber(number)
val sb = StringBuilder()
val money = getStringNumber(numbers.asInt())
val cents = getStringNumber(decimals.asInt())
if (money.isNotBlank())
sb.append(money).append(" reais")
if (cents.isNotBlank()) {
if (sb.isNotBlank())
sb.append(" e ")
sb.append(cents).append(if (cents == units[1]) " centavo" else " centavos")
}
return sb.toString()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment