Converting Words to Numbers in Java
I hope below code will do the job in most of the cases. However some modification might be required as I've not tested properly yet.
Assumption:
- Positive, negative, plus, minus is not allowed.
- Lac, crore is not allowed.
- Only English language is supported.
If you need to support first two points, you can very easily do that.
boolean isValidInput = true;
long result = 0;
long finalResult = 0;
List<String> allowedStrings = Arrays.asList
(
"zero","one","two","three","four","five","six","seven",
"eight","nine","ten","eleven","twelve","thirteen","fourteen",
"fifteen","sixteen","seventeen","eighteen","nineteen","twenty",
"thirty","forty","fifty","sixty","seventy","eighty","ninety",
"hundred","thousand","million","billion","trillion"
);
String input="One hundred two thousand and thirty four";
if(input != null && input.length()> 0)
{
input = input.replaceAll("-", " ");
input = input.toLowerCase().replaceAll(" and", " ");
String[] splittedParts = input.trim().split("\\s+");
for(String str : splittedParts)
{
if(!allowedStrings.contains(str))
{
isValidInput = false;
System.out.println("Invalid word found : "+str);
break;
}
}
if(isValidInput)
{
for(String str : splittedParts)
{
if(str.equalsIgnoreCase("zero")) {
result += 0;
}
else if(str.equalsIgnoreCase("one")) {
result += 1;
}
else if(str.equalsIgnoreCase("two")) {
result += 2;
}
else if(str.equalsIgnoreCase("three")) {
result += 3;
}
else if(str.equalsIgnoreCase("four")) {
result += 4;
}
else if(str.equalsIgnoreCase("five")) {
result += 5;
}
else if(str.equalsIgnoreCase("six")) {
result += 6;
}
else if(str.equalsIgnoreCase("seven")) {
result += 7;
}
else if(str.equalsIgnoreCase("eight")) {
result += 8;
}
else if(str.equalsIgnoreCase("nine")) {
result += 9;
}
else if(str.equalsIgnoreCase("ten")) {
result += 10;
}
else if(str.equalsIgnoreCase("eleven")) {
result += 11;
}
else if(str.equalsIgnoreCase("twelve")) {
result += 12;
}
else if(str.equalsIgnoreCase("thirteen")) {
result += 13;
}
else if(str.equalsIgnoreCase("fourteen")) {
result += 14;
}
else if(str.equalsIgnoreCase("fifteen")) {
result += 15;
}
else if(str.equalsIgnoreCase("sixteen")) {
result += 16;
}
else if(str.equalsIgnoreCase("seventeen")) {
result += 17;
}
else if(str.equalsIgnoreCase("eighteen")) {
result += 18;
}
else if(str.equalsIgnoreCase("nineteen")) {
result += 19;
}
else if(str.equalsIgnoreCase("twenty")) {
result += 20;
}
else if(str.equalsIgnoreCase("thirty")) {
result += 30;
}
else if(str.equalsIgnoreCase("forty")) {
result += 40;
}
else if(str.equalsIgnoreCase("fifty")) {
result += 50;
}
else if(str.equalsIgnoreCase("sixty")) {
result += 60;
}
else if(str.equalsIgnoreCase("seventy")) {
result += 70;
}
else if(str.equalsIgnoreCase("eighty")) {
result += 80;
}
else if(str.equalsIgnoreCase("ninety")) {
result += 90;
}
else if(str.equalsIgnoreCase("hundred")) {
result *= 100;
}
else if(str.equalsIgnoreCase("thousand")) {
result *= 1000;
finalResult += result;
result=0;
}
else if(str.equalsIgnoreCase("million")) {
result *= 1000000;
finalResult += result;
result=0;
}
else if(str.equalsIgnoreCase("billion")) {
result *= 1000000000;
finalResult += result;
result=0;
}
else if(str.equalsIgnoreCase("trillion")) {
result *= 1000000000000L;
finalResult += result;
result=0;
}
}
finalResult += result;
result=0;
System.out.println(finalResult);
}
}
package com;
import java.util.HashMap;
public class WordNNumber {
static HashMap<String, Integer> numbers= new HashMap<String, Integer>();
static HashMap<String, Integer> onumbers= new HashMap<String, Integer>();
static HashMap<String, Integer> tnumbers= new HashMap<String, Integer>();
static {
numbers.put("zero", 0);
numbers.put("one", 1);
numbers.put("two", 2);
numbers.put("three", 3);
numbers.put("four", 4);
numbers.put("five", 5);
numbers.put("six", 6);
numbers.put("seven", 7);
numbers.put("eight", 8);
numbers.put("nine", 9);
numbers.put("ten", 10);
numbers.put("eleven", 11);
numbers.put("twelve", 12);
numbers.put("thirteen", 13);
numbers.put("fourteen", 14);
numbers.put("fifteen", 15);
numbers.put("sixteen", 16);
numbers.put("seventeen", 17);
numbers.put("eighteen", 18);
numbers.put("nineteen", 19);
tnumbers.put("twenty", 20);
tnumbers.put("thirty", 30);
tnumbers.put("fourty", 40);
tnumbers.put("fifty", 50);
tnumbers.put("sixty", 60);
tnumbers.put("seventy", 70);
tnumbers.put("eighty", 80);
tnumbers.put("ninety", 90);
onumbers.put("hundred", 100);
onumbers.put("thousand", 1000);
onumbers.put("million", 1000000);
onumbers.put("billion", 1000000000);
//numbers.put("", );
}
public static void main(String args[]){
String input1="fifty five million twenty three thousand ninety one";
String input2="fifty five billion three thousand one";
String input3="fifty five million ninety one";
wordToNumber(input1);
wordToNumber(input2);
wordToNumber(input3);
}
private static void wordToNumber(String input) {
System.out.println("===========\nInput string = "+input);
long sum=0;
Integer temp=null;
Integer previous=0;
String [] splitted= input.toLowerCase().split(" ");
for(String split:splitted){
if( numbers.get(split)!=null){
temp= numbers.get(split);
sum=sum+temp;
previous=previous+temp;
}
else if(onumbers.get(split)!=null){
if(sum!=0){
sum=sum-previous;
}
sum=sum+(long)previous*(long)onumbers.get(split);
temp=null;
previous=0;
}
else if(tnumbers.get(split)!=null){
temp=tnumbers.get(split);
sum=sum+temp;
previous=temp;
}
}
System.out.println(sum);
}
}
Full credit to Kartic for the elegant answer. I've added to it to allow for processing a large block of text with these types of "word numbers" dispersed inside of it. Not as clean as I hoped since I have to process it without losing any formatting.
It's a work in progress but might be of some use to people: https://github.com/jgraham0325/words-to-numbers/blob/master/src/main/java/org/jg/wordstonumbers/WordsToNumbersUtil.java