Skip to main content

Words to Number Conversion

The wordsToNumber utility converts Persian word representations of numbers back to their numeric equivalents, with support for fuzzy matching and various input formats.

Basic Usage

import { wordsToNumber } from '@persian-tools/persian-tools';

Simple Conversion

wordsToNumber("یک هزار و دویست و سی و چهار");
// Output: 1234

wordsToNumber("صفر");
// Output: 0

wordsToNumber("یک میلیون");
// Output: 1000000

Advanced Options

The function accepts an optional configuration object:
interface WordsToNumberOptions {
	fuzzy?: boolean;
	digits?: "persian" | "english" | "both";
	addCommas?: boolean;
}

Fuzzy Matching

Enable fuzzy matching to handle variations in spacing and formatting:
// Exact matching (default)
wordsToNumber("یک هزار و دویست"); // 1200

// Fuzzy matching
wordsToNumber("یکهزار دویست", { fuzzy: true }); // 1200
wordsToNumber("یک هزاردویست", { fuzzy: true }); // 1200
wordsToNumber("یک‌هزار و دویست", { fuzzy: true }); // 1200

Mixed Digit Support

Handle input containing both Persian words and digits:
wordsToNumber("۱۲ هزار", { digits: "persian" }); // 12000
wordsToNumber("12 هزار", { digits: "english" }); // 12000
wordsToNumber("۱۲ هزار و 34", { digits: "both" }); // 12034

Comma Formatting

Return results with comma separators:
wordsToNumber("یک میلیون", { addCommas: true });
// Output: "1,000,000"

wordsToNumber("دو میلیارد", { addCommas: true });
// Output: "2,000,000,000"

Supported Word Patterns

Basic Numbers

wordsToNumber("یک"); // 1
wordsToNumber("ده"); // 10
wordsToNumber("یکصد"); // 100
wordsToNumber("هزار"); // 1000

Compound Numbers

wordsToNumber("بیست و یک"); // 21
wordsToNumber("سیصد و چهل و پنج"); // 345
wordsToNumber("یک هزار و نهصد"); // 1900

Large Numbers

wordsToNumber("یک میلیون"); // 1000000
wordsToNumber("دو میلیارد و پانصد میلیون"); // 2500000000
wordsToNumber("یک تریلیون"); // 1000000000000

Ordinal Numbers

Handle ordinal number words:
wordsToNumber("اول"); // 1
wordsToNumber("دوم"); // 2
wordsToNumber("سوم"); // 3
wordsToNumber("بیستم"); // 20
wordsToNumber("یکصدم"); // 100

Edge Cases and Error Handling

Invalid Input

wordsToNumber("نامعلوم"); // null
wordsToNumber(""); // null
wordsToNumber(null); // null
wordsToNumber(undefined); // null

Partial Matches

// With fuzzy matching
wordsToNumber("یک هزار ناقص", { fuzzy: true }); // 1000 (ignores "ناقص")

// Without fuzzy matching
wordsToNumber("یک هزار ناقص"); // null (exact match required)

Mixed Content

// Numbers mixed with text
wordsToNumber("حدود یک هزار", { fuzzy: true }); // 1000
wordsToNumber("تقریباً دو میلیون", { fuzzy: true }); // 2000000

Complex Examples

Real-world Input Variations

// Different spacing patterns
wordsToNumber("یک هزار و دویست", { fuzzy: true }); // 1200
wordsToNumber("یک‌هزار و دویست", { fuzzy: true }); // 1200
wordsToNumber("یکهزاردویست", { fuzzy: true }); // 1200

// Mixed digits and words
wordsToNumber("۱۵ هزار و ۲۰۰", {
	fuzzy: true,
	digits: "persian",
}); // 15200

// Currency context
wordsToNumber("یک میلیون تومان", { fuzzy: true }); // 1000000

Batch Processing

const persianNumbers = ["یک هزار", "دو هزار و پانصد", "سه میلیون", "چهار میلیارد"];

const converted = persianNumbers.map((text) => ({
	original: text,
	numeric: wordsToNumber(text),
	formatted: wordsToNumber(text, { addCommas: true }),
}));

Performance Considerations

  • Use exact matching when input format is consistent
  • Enable fuzzy matching only when needed (it’s slower)
  • Cache results for frequently converted phrases
  • Exact matching: ~0.2ms average
  • Fuzzy matching: ~1-3ms average
  • Mixed digits: ~0.5ms average

TypeScript Support

Full TypeScript definitions are provided:
import { wordsToNumber, WordsToNumberOptions } from "persian-tools";

const options: WordsToNumberOptions = {
	fuzzy: true,
	digits: "both",
	addCommas: false,
};

const result: number | null = wordsToNumber("یک هزار", options);

if (result !== null) {
	console.log(`Converted: ${result}`);
}

Common Use Cases

Form Input Processing

function processNumericInput(userInput: string): number | null {
	// Try exact match first (faster)
	let result = wordsToNumber(userInput);

	// Fall back to fuzzy matching
	if (result === null) {
		result = wordsToNumber(userInput, {
			fuzzy: true,
			digits: "both",
		});
	}

	return result;
}

Invoice Processing

function parseInvoiceAmount(text: string) {
	const amount = wordsToNumber(text, {
		fuzzy: true,
		digits: "both",
	});

	return {
		original: text,
		parsed: amount,
		formatted: amount ? addCommas(amount) : null,
		isValid: amount !== null,
	};
}

Voice Input Processing

function processVoiceInput(spokenText: string) {
	// Voice input often has spacing variations
	return wordsToNumber(spokenText, {
		fuzzy: true,
		digits: "both",
	});
}

Error Handling Best Practices

function safeWordsToNumber(input: string): number {
	const result = wordsToNumber(input, { fuzzy: true });

	if (result === null) {
		throw new Error(`Cannot convert "${input}" to number`);
	}

	return result;
}

// Or with default value
function wordsToNumberWithDefault(input: string, defaultValue = 0): number {
	return wordsToNumber(input, { fuzzy: true }) ?? defaultValue;
}