Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New Feature] Numbers to Word Representations Converter #6136

Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added a new feature to convert numbers into their word representation
ZingadePrathamesh committed Jan 14, 2025
commit 05e43376e711101e47d43d8466b4ff0c9e98691f
100 changes: 100 additions & 0 deletions src/main/java/com/thealgorithms/conversions/NumberToWords.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.thealgorithms.conversions;

import java.math.BigDecimal;

/**
A Java-based utility for converting numeric values into their English word
representations. Whether you need to convert a small number, a large number
with millions and billions, or even a number with decimal places, this utility
has you covered.
*
*/
public class NumberToWords {

private NumberToWords() {
}

private static final String[] units = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};

private static final String[] tens = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};

private static final String[] powers = {"", "Thousand", "Million", "Billion", "Trillion"};

private static final String ZERO = "Zero";
private static final String POINT = " Point";
private static final String NEGATIVE = "Negative ";

public static String convert(BigDecimal number) {
if (number == null) {
return "Invalid Input";
}

// Check for negative sign
boolean isNegative = number.signum() < 0;

// Split the number into whole and fractional parts
BigDecimal[] parts = number.abs().divideAndRemainder(BigDecimal.ONE);
BigDecimal wholePart = parts[0]; // Keep whole part as BigDecimal
String fractionalPartStr = parts[1].compareTo(BigDecimal.ZERO) > 0 ? parts[1].toPlainString().substring(2) : ""; // Get fractional part only if it exists

// Convert whole part to words
StringBuilder result = new StringBuilder();
if (isNegative) {
result.append(NEGATIVE);
}
result.append(convertWholeNumberToWords(wholePart));

// Convert fractional part to words
if (!fractionalPartStr.isEmpty()) {
result.append(POINT);
for (char digit : fractionalPartStr.toCharArray()) {
int digitValue = Character.getNumericValue(digit);
result.append(" ").append(digitValue == 0 ? ZERO : units[digitValue]);
}
}

return result.toString().trim();
}

private static String convertWholeNumberToWords(BigDecimal number) {
if (number.compareTo(BigDecimal.ZERO) == 0) {
return ZERO;
}

StringBuilder words = new StringBuilder();
int power = 0;

while (number.compareTo(BigDecimal.ZERO) > 0) {
// Get the last three digits
BigDecimal[] divisionResult = number.divideAndRemainder(BigDecimal.valueOf(1000));
int chunk = divisionResult[1].intValue();

if (chunk > 0) {
String chunkWords = convertChunk(chunk);
if (power > 0) {
words.insert(0, powers[power] + " ");
}
words.insert(0, chunkWords + " ");
}

number = divisionResult[0]; // Continue with the remaining part
power++;
}

return words.toString().trim();
}

private static String convertChunk(int number) {
String chunkWords;

if (number < 20) {
chunkWords = units[number];
} else if (number < 100) {
chunkWords = tens[number / 10] + (number % 10 > 0 ? " " + units[number % 10] : "");
} else {
chunkWords = units[number / 100] + " Hundred" + (number % 100 > 0 ? " " + convertChunk(number % 100) : "");
}

return chunkWords;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.thealgorithms.conversions;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.math.BigDecimal;
import org.junit.jupiter.api.Test;

public class NumberToWordsTest {

@Test
void testNullInput() {
assertEquals("Invalid Input", NumberToWords.convert(null), "Null input should return 'Invalid Input'");
}

@Test
void testZeroInput() {
assertEquals("Zero", NumberToWords.convert(BigDecimal.ZERO), "Zero input should return 'Zero'");
}

@Test
void testPositiveWholeNumbers() {
assertEquals("One", NumberToWords.convert(BigDecimal.ONE), "1 should convert to 'One'");
assertEquals("One Thousand", NumberToWords.convert(new BigDecimal("1000")), "1000 should convert to 'One Thousand'");
assertEquals("One Million", NumberToWords.convert(new BigDecimal("1000000")), "1000000 should convert to 'One Million'");
}

@Test
void testNegativeWholeNumbers() {
assertEquals("Negative One", NumberToWords.convert(new BigDecimal("-1")), "-1 should convert to 'Negative One'");
assertEquals("Negative One Thousand", NumberToWords.convert(new BigDecimal("-1000")), "-1000 should convert to 'Negative One Thousand'");
}

@Test
void testFractionalNumbers() {
assertEquals("Zero Point One Two Three", NumberToWords.convert(new BigDecimal("0.123")), "0.123 should convert to 'Zero Point One Two Three'");
assertEquals("Negative Zero Point Four Five Six", NumberToWords.convert(new BigDecimal("-0.456")), "-0.456 should convert to 'Negative Zero Point Four Five Six'");
}

@Test
void testLargeNumbers() {
assertEquals("Nine Hundred Ninety Nine Million Nine Hundred Ninety Nine Thousand Nine Hundred Ninety Nine", NumberToWords.convert(new BigDecimal("999999999")), "999999999 should convert correctly");
assertEquals("One Trillion", NumberToWords.convert(new BigDecimal("1000000000000")), "1000000000000 should convert to 'One Trillion'");
}

@Test
void testNegativeLargeNumbers() {
assertEquals("Negative Nine Trillion Eight Hundred Seventy Six Billion Five Hundred Forty Three Million Two Hundred Ten Thousand Nine Hundred Eighty Seven", NumberToWords.convert(new BigDecimal("-9876543210987")), "-9876543210987 should convert correctly");
}

@Test
void testFloatingPointPrecision() {
assertEquals("One Million Point Zero Zero One", NumberToWords.convert(new BigDecimal("1000000.001")), "1000000.001 should convert to 'One Million Point Zero Zero One'");
}

@Test
void testEdgeCases() {
assertEquals("Negative Zero", NumberToWords.convert(new BigDecimal("-0.0")), "-0.0 should convert to 'Negative Zero'");
assertEquals("Zero Point Zero Zero Zero Zero Zero Zero One", NumberToWords.convert(new BigDecimal("1E-7")), "1E-7 should convert to 'Zero Point Zero Zero Zero Zero Zero Zero One'");
}
}