Convert number to letter

Here is the Java Program :

package Practice.Program;

public class Num2Words {
  
  private static long number;
  private static String words = new String("");
  
  public Num2Words(long n){ number = n; }
  
  static String[] tp = {"", "thousand ", "million ", "billion ", "trillion ", "quadrillion ", "pentillion "};
  static String[] od = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
  static String[] td = {"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
  static String[] tn = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
  
  public String toWords(){
    words = Long.toString(number);
    int l = words.length();
    boolean n = false;
    
    if (number < 0){ n = true; number *= -1; --l;}
    
    breaker : for (byte LOL = 0; LOL < 1; LOL++){
      
      if (StringHasChar(words, '.')){ words = "Decimals not supported."; break breaker;}
      if (l>19){ words = "too big"; break breaker;}
      
      if (l==1)      words = oneDigit(number);                    // one digit
      
      else if (l==2) words = twoDigits(number);                   // two digits 
      
      else if (l==3) words = threeDigits(number);                 // three digits
      
      else words = nDigits(number);                               // multiple digits
      
    }
    
    if (n == true) {words = "Minus "+words; number *= -1;}
   return words;
  }
  
  private static String oneDigit(long n){
    char[] ns = Long.toString(n).toCharArray();
    return od[(char2num(ns[0]))];
  }
  
  private static String twoDigits(long n){
    String s = "";
    char[] ns = Long.toString(n).toCharArray();
    if (n < 20){
      s = td[(char2num(ns[1]))];
    } else if (n < 100){
        s = tn[char2num(ns[0])];
        if (char2num(ns[1])!=0){ s += " " + od[char2num(ns[1])]; }
      }
    return s;
  }
  
  private static String threeDigits(long n){
    String s = "", is = Long.toString(n);
    long[] ns = String2longArray(is);
    
    s = od[(int)(ns[0])] + " hundred";
    if (ns[1]!=0&&ns[2]!=0){
      long i = (ns[1])*10+(ns[2]);
      s += " " + twoDigits(i);
    } else {
        if (ns[1]!=0) s += " " + twoDigits((ns[1]*10)); 
        if (ns[2]!=0) s += " " + oneDigit(ns[2]);
      }
    
    return s;
  }
  
  private static String nDigits(long n){
    String s = threeDigits(n);
    int tpi = ((digits(n)+2)/3)-1, rtpi = 0;
    long[] tfr = threeFromRight(n);
    s = "";
    
    for (; tpi >= 0; tpi--, rtpi++){
      s = new Num2Words(tfr[tpi]).toWords() + " " + tp[rtpi] + s;
    }
    
    return s;
  }
  
  private static int digits(long n){
    long ans = 0;
    for (; n>0; n/=10, ans++);
    return (int)(ans);
  }
  
  private static long[] threeFromRight(long n){
    int tpi = (digits(n)+2)/3, nl = digits(n);
    long[] ans=new long[tpi], ia=String2longArray(Long.toString(n)), ta=new long[3];
    
    for (int i=nl, t=2, c=0, l=tpi*3; l >= 0; l--, c++, i--, t--){
      try {ta[t] = ia[i-1];}
      catch (ArrayIndexOutOfBoundsException e){ta[t]=0;}
      if (((c+1)%3)==0){ 
        --tpi;
        ans[tpi] = longArrays2long(ta);
        
        t = 3;
        c = -1;
      }
    }
    
    return ans;
  }
  
  private static int char2num(char c){
    char[] ca = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    byte ia[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},  ans = -1;
    
    for (byte i = 0; i < 10; i++){ if (c == ca[i]){ ans = ia[i]; break;} }
    return ans;
  }
  
  private static long[] String2longArray(String s){
    char[] ca = s.toCharArray();
    byte l = (byte)s.length();
    long[] ans = new long[l];
    
    for (byte i = 0; i < l; i++){ ans[i] = char2num(ca[i]); }
    return ans;
  }
  
  private static long longArrays2long(long[] ia){
    long ans = 0;
    try { for (int i = 0; i >= 0; ans += ia[i], ans *= 10, ++i); } 
    catch (ArrayIndexOutOfBoundsException e){}
    ans/=10;
    
    return ans;
  }
  
  private static boolean StringHasChar(String s, char c){
    char[] sca = s.toCharArray();
    byte l = (byte)(s.length());
    boolean ans = false;
    for (byte i = 0; i > l; i++){
      if (sca[i] == c) ans = true;
    }
    return ans;
  }
  
  public static void main(String[] args){
    long n = -1053664648543756767l;
    String words = new Num2Words(n).toWords();
    
    System.out.println(n + " : " + words);
  }
  
}

I've also posted my program as an answer to a question in Stack Overflow.


Would anyone like to help me out with putting some procedures into MIT AI2 ?

If Yes

How you can help me :-

  1. Make an aia.
  2. Make the procedures.
  3. Send the aia.

Helping me is fully your own wish. I'd not force anyone.

Thank You.

Why do you put your code in a stack overflow question from 2011! that is about converting a number to word in Iphone?

2 Likes

Didn't see the date actually. :sweat_smile:

Actually, a lot of Stack Overflow Java questions are old, some are the same age or just a year smaller than my age.

Back to the topic, I am making an extension out of this.

EDIT: Wait a minute...seems that there is something wrong in the code.

2 Likes

LOL :joy:

Same with me too, I'm just about to be 15, and these questions are almost 13 years old LOL. :joy:

Noice.

@Gordon_Lu

Wait what, where ?
I tested the code with many numbers, actually.

Obviously, its not possible to test it for pentillions of numbers actually. :sweat_smile:

EDIT :

You can use this code snippet to test any number you wish.

Just add that number to the long array and run your code and see the terminal. You'd get the result.

  
  public static void main(String[] args){
    long[] la = {836463837l, 8373647738147l, 82726361882l, 63652772l, 6726263637l};
    String words = "";
    try {  for (int i = 0; i>=0; i++){
             words = new Num2Words(la[i]).toWords();
             System.out.println(la[i] + " : " + words);
           }
    } catch (ArrayIndexOutOfBoundsException e){}
  }
  

Pls tell me if you find any mistake and I'll fix it.

Pls don't forget to give me a small credit if you use my code. I never got a credit b4. :cry:

This is from the Stack Overflow answer that received 100+ upvotes, and is capable of 12 digits in English. I will post it like an extension here.

Successfully made English translation. I am still working on it.

image

Note: if you want to do this in Screen.Initialize, you need to wait 200 ms first in order to start converting.

1 Like

Ok, just do it. :upside_down_face:

I'm make mine myself when learn about making them.

Finally completed, English and French. Currently, this is only capable of 12 digits (hundred billions).

Event blocks

GotResult

image

This event is fired when the extension has received the conversion result.

Parameters: languageCode = text, result = text

Method blocks

NumbersToEnglish

image

Converts numbers to English numerals and calls the GotResult event when this is finished.

Parameters: number = (long)

NumbersToFrench

image

Converts numbers to French numerals and calls the GotResult event when this is finished.

Parameters: number = (long)

:inbox_tray: Downloads

AIX:
com.gordonlu.numbers2words.aix (9.9 KB)

:lock: Open Source

Here you go.

package com.gordonlu.numbers2words;

import android.app.Activity;
import android.content.Context;
import com.google.appinventor.components.annotations.*;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;

import java.text.DecimalFormat;
import java.util.Arrays;
import java.lang.Integer;

@DesignerComponent(
        version = 1,
        description = "A non-visible extension that automatically converts numbers to words.",
        category = ComponentCategory.EXTENSION,
        nonVisible = true,
        iconName = "https://docs.google.com/drawings/d/e/2PACX-1vQCI87PHLBF0jb8QWyYmIRQSjjNW3EFXf-qpsWCvBYkUQ9vEgPAB8SpxcMpblxNpbIYrjCjLrRLIU2c/pub?w=16&h=16")

@SimpleObject(external = true)
//Libraries
@UsesLibraries(libraries = "")
//Permissions
@UsesPermissions(permissionNames = "")

public class Numbers2Words extends AndroidNonvisibleComponent {

    //Activity and Context
    private Context context;
    private Activity activity;

    public Numbers2Words(ComponentContainer container){
        super(container.$form());
        this.activity = container.$context();
        this.context = container.$context();
    }

    // https://stackoverflow.com/a/3911987/17802442

    private static final String[] tensNames = {""," ten"," twenty"," thirty"," forty"," fifty"," sixty"," seventy"," eighty"," ninety"};

    private static final String[] numNames = {""," one"," two"," three"," four"," five"," six"," seven"," eight"," nine"," ten",
    " eleven"," twelve"," thirteen"," fourteen"," fifteen"," sixteen"," seventeen"," eighteen"," nineteen"
  };

  private static final String[] dizaineNames = { "","","vingt","trente","quarante","cinquante","soixante","soixante","quatre-vingt","quatre-vingt"};

  private static final String[] uniteNames1 = {"","un","deux","trois","quatre","cinq","six","sept","huit","neuf","dix","onze","douze","treize","quatorze",
    "quinze","seize","dix-sept","dix-huit","dix-neuf"};

  private static final String[] uniteNames2 = {"","","deux","trois","quatre","cinq","six","sept","huit","neuf","dix"};

    private static String convertLessThanOneThousand(int number) {
        String soFar;
        if (number % 100 < 20){
            soFar = numNames[number % 100];
            number /= 100;
        } else {
            soFar = numNames[number % 10];
            number /= 10;
            soFar = tensNames[number % 10] + soFar;
            number /= 10;
        }
        if (number == 0) return soFar;
        return numNames[number] + " hundred" + soFar;
    }

    public static String convert(long number) {
        if (number == 0) { 
            return "zero"; 
        }
        String snumber = Long.toString(number);
        String mask = "000000000000";
        DecimalFormat df = new DecimalFormat(mask);
        snumber = df.format(number);
        int billions = Integer.parseInt(snumber.substring(0,3));
        int millions  = Integer.parseInt(snumber.substring(3,6));
        int hundredThousands = Integer.parseInt(snumber.substring(6,9));
        int thousands = Integer.parseInt(snumber.substring(9,12));

        String tradBillions;
        switch (billions) {
        case 0:
            tradBillions = "";
            break;
        case 1 :
            tradBillions = convertLessThanOneThousand(billions) + " billion ";
            break;
        default :
            tradBillions = convertLessThanOneThousand(billions) + " billion ";
        }
        String result =  tradBillions;
        String tradMillions;
        switch (millions) {
        case 0:
            tradMillions = "";
            break;
        case 1 :
            tradMillions = convertLessThanOneThousand(millions) + " million ";
            break;
        default :
            tradMillions = convertLessThanOneThousand(millions) + " million ";
    }
    result =  result + tradMillions;
    String tradHundredThousands;
    switch (hundredThousands) {
    case 0:
      tradHundredThousands = "";
      break;
    case 1 :
      tradHundredThousands = "one thousand ";
      break;
    default :
      tradHundredThousands = convertLessThanOneThousand(hundredThousands)
         + " thousand ";
    }
    result =  result + tradHundredThousands;
    String tradThousand;
    tradThousand = convertLessThanOneThousand(thousands);
    result =  result + tradThousand;
    return result.replaceAll("^\\s+", "").replaceAll("\\b\\s{2,}\\b", " ");
  }

    @SimpleFunction(description = "Converts numbers to English numerals and calls the GotResult event when this is finished.")
    public void NumbersToEnglish(long number) {
        String result = convert(number);
        GotResult("en", result);
    }

    @SimpleFunction(description = "Converts numbers to French numerals and calls the GotResult event when this is finished.")
    public void NumbersToFrench(long number) {
        String result = convertF(number);
        GotResult("fr", result);
    }

    @SimpleEvent(description = "This event is fired when the extension has received the conversion result.")
    public void GotResult(String languageCode, String result) {
        EventDispatcher.dispatchEvent(this, "GotResult", languageCode, result);
    }

  private static String convertZeroToHundred(int number) {
    int laDizaine = number / 10;
    int lUnite = number % 10;
    String resultat = "";
    switch (laDizaine) {
    case 1 :
    case 7 :
    case 9 :
      lUnite = lUnite + 10;
      break;
    default:
    }
    String laLiaison = "";
    if (laDizaine > 1) {
      laLiaison = "-";
    }
    switch (lUnite) {
    case 0:
      laLiaison = "";
      break;
    case 1 :
      if (laDizaine == 8) {
        laLiaison = "-";
      }
      else {
        laLiaison = " et ";
      }
      break;
    case 11 :
      if (laDizaine==7) {
        laLiaison = " et ";
      }
      break;
    default:
    }
    switch (laDizaine) {
    case 0:
      resultat = uniteNames1[lUnite];
      break;
    case 8 :
      if (lUnite == 0) {
        resultat = dizaineNames[laDizaine];
      }
      else {
        resultat = dizaineNames[laDizaine] + laLiaison + uniteNames1[lUnite];
      }
      break;
    default :
      resultat = dizaineNames[laDizaine] + laLiaison + uniteNames1[lUnite];
    }
    return resultat;
  }

  private static String convertLessThanOneThousandF(int number) {
    int lesCentaines = number / 100;
    int leReste = number % 100;
    String sReste = convertZeroToHundred(leReste);
    String resultat;
    switch (lesCentaines) {
    case 0:
      resultat = sReste;
      break;
    case 1 :
      if (leReste > 0) {
        resultat = "cent " + sReste;
      }
      else {
        resultat = "cent";
      }
      break;
    default :
      if (leReste > 0) {
        resultat = uniteNames2[lesCentaines] + " cent " + sReste;
      }
      else {
        resultat = uniteNames2[lesCentaines] + " cents";
      }
    }
    return resultat;
  }

  public static String convertF(long number) {
    if (number == 0) { return "zéro"; }
    String snumber = Long.toString(number);
    String mask = "000000000000";
    DecimalFormat df = new DecimalFormat(mask);
    snumber = df.format(number);
    int lesMilliards = Integer.parseInt(snumber.substring(0,3));
    int lesMillions  = Integer.parseInt(snumber.substring(3,6));
    int lesCentMille = Integer.parseInt(snumber.substring(6,9));
    int lesMille = Integer.parseInt(snumber.substring(9,12));
    String tradMilliards;
    switch (lesMilliards) {
    case 0:
      tradMilliards = "";
      break;
    case 1 :
      tradMilliards = convertLessThanOneThousandF(lesMilliards)
         + " milliard ";
      break;
    default :
      tradMilliards = convertLessThanOneThousandF(lesMilliards)
         + " milliards ";
    }
    String resultat =  tradMilliards;

    String tradMillions;
    switch (lesMillions) {
    case 0:
      tradMillions = "";
      break;
    case 1 :
      tradMillions = convertLessThanOneThousandF(lesMillions)
         + " million ";
      break;
    default :
      tradMillions = convertLessThanOneThousandF(lesMillions)
         + " millions ";
    }
    resultat =  resultat + tradMillions;

    String tradCentMille;
    switch (lesCentMille) {
    case 0:
      tradCentMille = "";
      break;
    case 1 :
      tradCentMille = "mille ";
      break;
    default :
      tradCentMille = convertLessThanOneThousandF(lesCentMille)
         + " mille ";
    }
    resultat =  resultat + tradCentMille;

    String tradMille;
    tradMille = convertLessThanOneThousandF(lesMille);
    resultat =  resultat + tradMille;

    return resultat;
  }
}

2 Likes

All well and good, but you started this Topic with a different requirement - to "convert number to letter", thus wasting a lot of our time!

1 Like

@ChrisWard

Are u somehow meaning that I started the topic ?

LOL :joy:

If you actually mean that I stated the topic, click here

This topic was actually started by @BLACK_GHOST

1 Like

Sorry Shubhamr69, of course you are not the author of this Topic, my mistake.

Your effort does not meet Black Ghost's requirement though, unless/he she has moved the original goal posts into midfield.

For your interest (and for resolving the potential misinformation), it is possible to achieve indexOf (index of character) and charAt (character at index) in App Inventor.

Here is how to get the index of character (and if it doesn't exists, it will return 0.):

And for "getting character at specific index", we already have a segment text block, but you can convert text to character list (from above) and use select list item too.

Finally, you mention matches() is not possible in App Inventor which matches() just checks if value is same with second value, and you can achieve with logic compare block.

logic_compare

2 Likes

That is the reason why I deleted my project.

Though I still had some methods which took me ages to find the blocks combination.

I didn't know that logic compare block compares texts.

Why a event block needed? A direct output plug will be fine.

text compares = is more advised, but the logic equals block also works.

3 Likes

It takes some time to calculate.

3 posts were split to a new topic: Convert English words to number