How to convert numbers from 0 to 999,999,999,999,999 (up to 999 trillion) into English words in Scala

1 Answer

0 votes
object NumberToWords {

  /*
      Convert numbers to English words in Scala
      -----------------------------------------
      Supports numbers from 0 to 999,999,999,999,999.

      Strategy:
      - Break the number into named groups: trillions, billions, millions,
        thousands, hundreds.
      - Convert each 0–999 group using a helper method.
      - Append group names ("trillion", "billion", etc.) when needed.
      - Build the final string using a ListBuffer and mkString for efficiency.
  */

  private val ones: Vector[String] = Vector(
    "zero", "one", "two", "three", "four",
    "five", "six", "seven", "eight", "nine",
    "ten", "eleven", "twelve", "thirteen", "fourteen",
    "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
  )

  private val tensWords: Vector[String] = Vector(
    "", "", "twenty", "thirty", "forty",
    "fifty", "sixty", "seventy", "eighty", "ninety"
  )

  /*
      appendWord:
      Adds a word to the output buffer.
  */
  private def appendWord(out: scala.collection.mutable.ListBuffer[String], word: String): Unit =
    if (word.nonEmpty) out += word

  /*
      convertHundreds:
      Converts numbers from 0 to 999 into words.
  */
  private def convertHundreds(n0: Long, out: scala.collection.mutable.ListBuffer[String]): Unit = {
    var n: Long = n0

    if (n == 0) return

    if (n >= 100) {
      appendWord(out, ones((n / 100).toInt))
      appendWord(out, "hundred")
      n %= 100
      if (n > 0) appendWord(out, "and")
    }

    if (n >= 20) {
      appendWord(out, tensWords((n / 10).toInt))
      if (n % 10 != 0) appendWord(out, ones((n % 10).toInt))
    } else if (n > 0) {
      appendWord(out, ones(n.toInt))
    }
  }

  /*
      numberToWords:
      Converts any number from 0 to 999,999,999,999,999 into English words.
  */
  def numberToWords(num: Long): String = {
    if (num == 0) return "zero"

    val out = scala.collection.mutable.ListBuffer[String]()

    val trillions: Long = num / 1_000_000_000_000L
    val billions: Long  = (num / 1_000_000_000L) % 1000
    val millions: Long  = (num / 1_000_000L) % 1000
    val thousands: Long = (num / 1_000L) % 1000
    val hundreds: Long  = num % 1000

    if (trillions > 0) {
      convertHundreds(trillions, out)
      appendWord(out, "trillion")
    }

    if (billions > 0) {
      convertHundreds(billions, out)
      appendWord(out, "billion")
    }

    if (millions > 0) {
      convertHundreds(millions, out)
      appendWord(out, "million")
    }

    if (thousands > 0) {
      convertHundreds(thousands, out)
      appendWord(out, "thousand")
    }

    if (hundreds > 0) {
      convertHundreds(hundreds, out)
    }

    out.mkString(" ")
  }

  /*
      main:
      Demonstrates usage with multiple test numbers.
  */
  def main(args: Array[String]): Unit = {
    val tests: Vector[Long] = Vector(
      1_234,
      12_345,
      123_456,
      1_234_567,
      123_456_789,
      12_345_678_901L,
      1_234_567_890_123L,
      999_999_999_999_999L
    )

    tests.foreach(n => println(s"$n -> ${numberToWords(n)}"))
  }
}


/*
run:

1234 -> one thousand two hundred and thirty four
12345 -> twelve thousand three hundred and forty five
123456 -> one hundred and twenty three thousand four hundred and fifty six
1234567 -> one million two hundred and thirty four thousand five hundred and sixty seven
123456789 -> one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine
12345678901 -> twelve billion three hundred and forty five million six hundred and seventy eight thousand nine hundred and one
1234567890123 -> one trillion two hundred and thirty four billion five hundred and sixty seven million eight hundred and ninety thousand one hundred and twenty three
999999999999999 -> nine hundred and ninety nine trillion nine hundred and ninety nine billion nine hundred and ninety nine million nine hundred and ninety nine thousand nine hundred and ninety nine

*/

 



answered Sep 6 by avibootz

Related questions

...