Skip to content

Instantly share code, notes, and snippets.

@bluemix
Last active August 24, 2023 19:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bluemix/c8ea6ba6be7edfcc048610e6cb95f992 to your computer and use it in GitHub Desktop.
Save bluemix/c8ea6ba6be7edfcc048610e6cb95f992 to your computer and use it in GitHub Desktop.
Converts numbers to Arabic words
import java.lang.StringBuilder
import java.math.BigDecimal
import java.math.BigInteger
import java.math.RoundingMode
import java.util.ArrayList
object ArabicTools {
fun numberToArabicWords(n: String?): String {
return numberToArabicWords(n, false)
}
fun numberToArabicWords(number: String?, isFeminine: Boolean): String {
return numberToArabicWords(BigInteger(number), isFeminine)
}
fun numberToArabicWords(number: BigInteger, isFeminine: Boolean): String {
return convertToArabic(number, isFeminine).trim { it <= ' ' }
}
private fun convertToArabic(number: BigInteger, isFeminine: Boolean): String {
if (number == BigInteger.ZERO) {
return "صفر"
}
var tempNumber = BigDecimal(number)
val result = StringBuilder()
var group: Short = 0
while (tempNumber >= BigDecimal.ONE) {
// separate number into groups
val numberToProcess = tempNumber.remainder(BigDecimal("1000"))
tempNumber = tempNumber.divide(BigDecimal("1000"))
// convert group into its text
val tempValue: Int = tempNumber.setScale(0, RoundingMode.FLOOR).toInt()
val groupDescription = processArabicGroup(numberToProcess.toInt(), group.toInt(), tempValue, isFeminine)
if (groupDescription.isNotEmpty()) { // here we add the new converted group to the previous concatenated text
if (group > 0) {
if (result.isNotEmpty()) {
result.insert(0, "و " + " ")
}
if (numberToProcess.compareTo(BigDecimal(2)) != 0) {
if (numberToProcess.remainder(BigDecimal("100")).compareTo(BigDecimal.ONE) != 0) {
if (numberToProcess >= BigDecimal("3") && numberToProcess <= BigDecimal("10")) { // for numbers between 3 and 9 we use plural name
result.insert(0, Words.arabicPluralGroups[group.toInt()] + " ")
} else {
if (result.isNotEmpty()) { // use appending case
result.insert(0, Words.arabicAppendedGroup[group.toInt()] + " ")
} else {
result.insert(0, Words.arabicGroup[group.toInt()] + " ") // use normal case
}
}
}
}
}
result.insert(0, "$groupDescription ")
}
group++
}
return if (result.isNotEmpty()) result.toString() else ""
}
private fun processArabicGroup(groupNumber: Int, groupLevel: Int, remainingNumber: Int, isFeminine: Boolean): String {
var tens = groupNumber % 100
val hundreds = groupNumber / 100
var result = ""
if (hundreds > 0) {
result = if (tens == 0 && hundreds == 2) { // حالة المضاف
if (groupLevel == 0) {
Words.arabicHundreds[hundreds]
} else {
Words.arabicAppendedTwos[0]
}
} else { // الحالة العادية
Words.arabicHundreds[hundreds]
}
}
if (tens > 0) {
if (tens < 20) { // if we are processing under 20 numbers
if (tens == 2 && hundreds == 0 && groupLevel > 0) { // This is special case for number 2 when it comes alone in the group
result = Words.arabicTwos[groupLevel] // في حالة الافراد
} else { // General case
if (result.isNotEmpty()) result += " و"
result += if (tens == 1 && groupLevel > 0) Words.arabicGroup[groupLevel] else if ((tens == 1 || tens == 2)
&& (groupLevel == 0 || groupLevel == -1)
&& hundreds == 0 && remainingNumber == 0
) "" // Special case for 1 and 2 numbers like: ليرة سورية و ليرتان سوريتان
else getDigitFeminineStatus(tens, groupLevel, isFeminine) // Get Feminine status for this digit
}
} else {
val ones = tens % 10
tens = tens / 10 - 2 // 20's offset
if (ones > 0) {
if (result.isNotEmpty()) result += " و"
// Get Feminine status for this digit
result += getDigitFeminineStatus(ones, groupLevel, isFeminine)
}
if (result.isNotEmpty()) result += " و"
// Get Tens text
result += Words.arabicTens[tens]
}
}
return result
}
private fun getDigitFeminineStatus(digit: Int, groupLevel: Int, isFeminine: Boolean): String {
return if (groupLevel == -1 || groupLevel == 0) {
if (!isFeminine) {
Words.arabicOnes[digit]
} else Words.arabicFeminineOnes[digit]
} else Words.arabicOnes[digit]
}
}
object Words {
val arabicOnes: MutableList<String> = ArrayList()
val arabicFeminineOnes: MutableList<String> = ArrayList()
val arabicTens: MutableList<String> = ArrayList()
val arabicHundreds: MutableList<String> = ArrayList()
val arabicTwos: MutableList<String> = ArrayList()
val arabicAppendedTwos: MutableList<String> = ArrayList()
val arabicGroup: MutableList<String> = ArrayList()
val arabicAppendedGroup: MutableList<String> = ArrayList()
val arabicPluralGroups: MutableList<String> = ArrayList()
init {
/* Ones */
arabicOnes.add("")
arabicOnes.add("واحد")
arabicOnes.add("اثنان")
arabicOnes.add("ثلاثة")
arabicOnes.add("أربعة")
arabicOnes.add("خمسة")
arabicOnes.add("ستة")
arabicOnes.add("سبعة")
arabicOnes.add("ثمانية")
arabicOnes.add("تسعة")
arabicOnes.add("عشرة")
arabicOnes.add("أحد عشر")
arabicOnes.add("اثنا عشر")
arabicOnes.add("ثلاثة عشر")
arabicOnes.add("أربعة عشر")
arabicOnes.add("خمسة عشر")
arabicOnes.add("ستة عشر")
arabicOnes.add("سبعة عشر")
arabicOnes.add("ثمانية عشر")
arabicOnes.add("تسعة عشر")
arabicFeminineOnes.add("")
arabicFeminineOnes.add("إحدى")
arabicFeminineOnes.add("اثنتان")
arabicFeminineOnes.add("ثلاث")
arabicFeminineOnes.add("أربع")
arabicFeminineOnes.add("خمس")
arabicFeminineOnes.add("ست")
arabicFeminineOnes.add("سبع")
arabicFeminineOnes.add("ثمان")
arabicFeminineOnes.add("تسع")
arabicFeminineOnes.add("عشر")
arabicFeminineOnes.add("إحدى عشرة")
arabicFeminineOnes.add("اثنتا عشرة")
arabicFeminineOnes.add("ثلاث عشرة")
arabicFeminineOnes.add("أربع عشرة")
arabicFeminineOnes.add("خمس عشرة")
arabicFeminineOnes.add("ست عشرة")
arabicFeminineOnes.add("سبع عشرة")
arabicFeminineOnes.add("ثماني عشرة")
arabicFeminineOnes.add("تسع عشرة")
/* Ones */
/* Tens */arabicTens.add("عشرون")
arabicTens.add("ثلاثون")
arabicTens.add("أربعون")
arabicTens.add("خمسون")
arabicTens.add("ستون")
arabicTens.add("سبعون")
arabicTens.add("ثمانون")
arabicTens.add("تسعون")
/* Tens */
/* Hundreds */arabicHundreds.add("")
arabicHundreds.add("مائة")
arabicHundreds.add("مئتان")
arabicHundreds.add("ثلاثمائة")
arabicHundreds.add("أربعمائة")
arabicHundreds.add("خمسمائة")
arabicHundreds.add("ستمائة")
arabicHundreds.add("سبعمائة")
arabicHundreds.add("ثمانمائة")
arabicHundreds.add("تسعمائة")
/* Hundreds */
/* Twos */arabicTwos.add("مئتان")
arabicTwos.add("ألفان")
arabicTwos.add("مليونان")
arabicTwos.add("ملياران")
arabicTwos.add("تريليونان")
arabicTwos.add("كوادريليونان")
arabicTwos.add("كوينتليونان")
arabicTwos.add("سكستيليونان")
arabicAppendedTwos.add("مئتا")
arabicAppendedTwos.add("ألفا")
arabicAppendedTwos.add("مليونا")
arabicAppendedTwos.add("مليارا")
arabicAppendedTwos.add("تريليونا")
arabicAppendedTwos.add("كوادريليونا")
arabicAppendedTwos.add("كوينتليونا")
arabicAppendedTwos.add("سكستيليونا")
/* Appended */
/* Twos */
/* Group */arabicGroup.add("مائة")
arabicGroup.add("ألف")
arabicGroup.add("مليون")
arabicGroup.add("مليار")
arabicGroup.add("تريليون")
arabicGroup.add("كوادريليون")
arabicGroup.add("كوينتليون")
arabicGroup.add("سكستيليون")
arabicAppendedGroup.add("")
arabicAppendedGroup.add("ألفاً")
arabicAppendedGroup.add("مليوناً")
arabicAppendedGroup.add("ملياراً")
arabicAppendedGroup.add("تريليوناً")
arabicAppendedGroup.add("كوادريليوناً")
arabicAppendedGroup.add("كوينتليوناً")
arabicAppendedGroup.add("سكستيليوناً")
/* Appended */
/* Group */
/* Plural groups*/arabicPluralGroups.add("")
arabicPluralGroups.add("آلاف")
arabicPluralGroups.add("ملايين")
arabicPluralGroups.add("مليارات")
arabicPluralGroups.add("تريليونات")
arabicPluralGroups.add("كوادريليونات")
arabicPluralGroups.add("كوينتليونات")
arabicPluralGroups.add("سكستيليونات")
/* Plural groups*/
}
}
@bluemix
Copy link
Author

bluemix commented Sep 6, 2021

Usage:

  val pronounceNumberWords = 
  	ArabicTools.numberToArabicWords("148503813473345")
  
// مائة و ثمانية و أربعون تريليوناً و خمسمائة و ثلاثة ملياراً و ثمانمائة 
// و ثلاثة عشر مليوناً و أربعمائة و ثلاثة و سبعون ألفاً و ثلاثمائة و خمس و أربعون

number to Arabic words code using Kotlin programming language

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment