CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-num2words

Modules to convert numbers to words in multiple languages with support for 50+ locales.

Pending
Overview
Eval results
Files

utility-functions.mddocs/

Utility Functions

Helper functions that support the core num2words functionality, including currency processing, number manipulation, and Python 2/3 compatibility. These utilities are used internally by the converters but can also be accessed directly for advanced usage.

Capabilities

Currency Processing Utilities

Functions for parsing and processing currency values with proper decimal handling.

def parse_currency_parts(value, is_int_with_cents=True):
    """
    Parse currency value into integer and cents components.
    
    Handles various input types and applies proper rounding for currency precision.
    
    Parameters:
    - value: int/float/Decimal/str - Currency value to parse
    - is_int_with_cents: bool - Treat integer inputs as cents (default: True)
    
    Returns:
    tuple - (integer_part, cents_part, is_negative)
    
    Raises:
    ValueError - For invalid currency value formats
    """

Usage Examples:

from num2words.currency import parse_currency_parts

# Float parsing with automatic rounding
integer, cents, negative = parse_currency_parts(42.567)
# (42, 57, False) - rounded to nearest cent

# Integer as cents (default behavior)
integer, cents, negative = parse_currency_parts(4250)
# (42, 50, False) - 4250 cents = 42.50 units

# Integer as whole units
integer, cents, negative = parse_currency_parts(42, is_int_with_cents=False)
# (42, 0, False) - 42 whole units, no cents

# String input parsing
integer, cents, negative = parse_currency_parts("42.50")
# (42, 50, False)

integer, cents, negative = parse_currency_parts("-123.45")
# (123, 45, True) - negative flag set

# Decimal precision handling
integer, cents, negative = parse_currency_parts(42.999)
# (43, 0, False) - rounds to nearest cent using ROUND_HALF_UP

# Edge cases
integer, cents, negative = parse_currency_parts(0.01)
# (0, 1, False) - minimum positive value

integer, cents, negative = parse_currency_parts(-0.50)
# (0, 50, True) - negative cents only

Currency Form Utilities

Functions for manipulating currency form strings with prefixes and adjectives.

def prefix_currency(prefix, base):
    """
    Add prefix to currency forms for adjective support.
    
    Parameters:
    - prefix: str - Prefix to add (e.g., "European", "American")
    - base: tuple - Base currency forms (singular, plural)
    
    Returns:
    tuple - Prefixed forms (prefixed_singular, prefixed_plural)
    """

Usage Examples:

from num2words.currency import prefix_currency

# Add nationality adjectives
euro_forms = ('euro', 'euros')
prefixed_euro = prefix_currency('European', euro_forms)
# ('European euro', 'European euros')

dollar_forms = ('dollar', 'dollars')
prefixed_dollar = prefix_currency('American', dollar_forms)
# ('American dollar', 'American dollars')

# Use with currency conversion
# These prefixed forms are used when adjective=True in to_currency()

Number String Processing Utilities

Functions for manipulating and splitting number strings.

def splitbyx(n, x, format_int=True):
    """
    Split number string into chunks of x digits.
    
    Useful for processing large numbers in groups (e.g., thousands, millions).
    
    Parameters:
    - n: str - Number string to split
    - x: int - Chunk size (number of digits per chunk)
    - format_int: bool - Convert chunks to integers (default: True)
    
    Yields:
    int/str - Number chunks from left to right
    """

Usage Examples:

from num2words.utils import splitbyx

# Split by thousands (3 digits)
number_str = "1234567890"
chunks = list(splitbyx(number_str, 3))
# [1, 234, 567, 890]

# Split with string preservation
chunks = list(splitbyx(number_str, 3, format_int=False))
# ['1', '234', '567', '890']

# Different chunk sizes
chunks = list(splitbyx("12345678", 4))
# [1234, 5678]

chunks = list(splitbyx("12345678", 2))
# [12, 34, 56, 78]

# Handle numbers shorter than chunk size
chunks = list(splitbyx("123", 5))
# [123] - single chunk when number is shorter

# Real-world usage in number processing
def process_large_number(num_str):
    """Example of using splitbyx for number word generation."""
    chunks = list(splitbyx(num_str, 3))  # Split by thousands
    # Process each chunk with appropriate scale (thousands, millions, etc.)
    return chunks

Digit Extraction Utilities

Functions for extracting and processing individual digits.

def get_digits(n):
    """
    Extract last 3 digits of number as reversed list.
    
    Useful for processing hundreds, tens, and units places.
    
    Parameters:
    - n: int - Number to extract digits from
    
    Returns:
    list - List of last 3 digits in reverse order [units, tens, hundreds]
    """

Usage Examples:

from num2words.utils import get_digits

# Basic digit extraction
digits = get_digits(123)
# [3, 2, 1] - units, tens, hundreds

digits = get_digits(45)
# [5, 4, 0] - units, tens, (zero) hundreds

digits = get_digits(7)
# [7, 0, 0] - units, (zero) tens, (zero) hundreds

digits = get_digits(1000)
# [0, 0, 0] - last 3 digits of 1000

digits = get_digits(1234)
# [4, 3, 2] - last 3 digits: 234 reversed

# Usage in number word generation
def process_hundreds(n):
    """Example of using get_digits for word generation."""
    units, tens, hundreds = get_digits(n)
    
    words = []
    if hundreds:
        words.append(f"{digit_words[hundreds]} hundred")
    if tens >= 2:
        words.append(f"{tens_words[tens]}")
        if units:
            words.append(f"{digit_words[units]}")
    elif tens == 1:
        words.append(f"{teens_words[units]}")
    elif units:
        words.append(f"{digit_words[units]}")
    
    return " ".join(words)

Python Compatibility Utilities

Functions for maintaining compatibility between Python 2 and Python 3.

def to_s(val):
    """
    Convert value to string with Python 2/3 compatibility.
    
    Handles unicode/str differences between Python versions.
    
    Parameters:
    - val: Any - Value to convert to string
    
    Returns:
    str/unicode - String representation appropriate for Python version
    """

Usage Examples:

from num2words.compat import to_s

# Safe string conversion across Python versions
text = to_s(42)           # "42"
text = to_s(42.5)         # "42.5"
text = to_s("hello")      # "hello"

# Handles unicode properly in both Python 2 and 3
unicode_text = to_s("café")  # Proper encoding handling

# Used internally by converters for consistent string handling
def safe_word_join(words):
    """Example internal usage."""
    return " ".join(to_s(word) for word in words)

String Type Detection

Compatibility utilities for string type checking.

# String type compatibility
strtype = basestring  # Python 2
strtype = str         # Python 3 (when basestring not available)

Usage Examples:

from num2words.compat import strtype

# Type checking that works across Python versions
def is_string_input(value):
    """Check if input is a string type."""
    return isinstance(value, strtype)

# Example usage in validation
def validate_input(value):
    """Validate input type for conversion."""
    if is_string_input(value):
        # Handle string input
        return float(value)
    elif isinstance(value, (int, float)):
        # Handle numeric input
        return value
    else:
        raise TypeError(f"Unsupported input type: {type(value)}")

Decimal Processing Utilities

High-precision decimal operations used in currency conversion.

# Decimal rounding modes
from decimal import ROUND_HALF_UP, Decimal

# Used internally for currency precision
def quantize_currency(value):
    """Round currency value to 2 decimal places."""
    return Decimal(str(value)).quantize(
        Decimal('.01'),
        rounding=ROUND_HALF_UP
    )

Usage Examples:

from decimal import Decimal, ROUND_HALF_UP

# Precise currency rounding (used internally)
value = Decimal('42.567')
rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
# Decimal('42.57')

# Handle edge cases in rounding
value = Decimal('42.565')
rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
# Decimal('42.57') - rounds up at .5

value = Decimal('42.564')
rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
# Decimal('42.56') - rounds down below .5

Internal Processing Helpers

Utilities used internally by the converter classes.

# Number component processing
def split_currency_components(value):
    """Split currency value maintaining precision."""
    if isinstance(value, int):
        # Assume cents if integer
        negative = value < 0
        value = abs(value)
        integer, cents = divmod(value, 100)
    else:
        # Handle float/Decimal with rounding
        value = Decimal(str(value))
        value = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
        negative = value < 0
        value = abs(value)
        integer, fraction = divmod(value, 1)
        cents = int(fraction * 100)
    
    return int(integer), cents, negative

# String cleaning and normalization  
def normalize_number_string(num_str):
    """Clean and normalize number string input."""
    # Remove common formatting characters
    cleaned = num_str.replace(',', '').replace(' ', '')
    
    # Handle negative signs
    if cleaned.startswith('-'):
        return '-', cleaned[1:]
    else:
        return '', cleaned

Advanced Usage Examples

Combining utilities for custom number processing.

from num2words.utils import splitbyx, get_digits
from num2words.currency import parse_currency_parts
from num2words.compat import to_s

def custom_number_processor(value):
    """Example of combining utilities for custom processing."""
    
    # Parse as currency to get components
    integer, cents, negative = parse_currency_parts(value)
    
    # Process large integer part in chunks
    if integer >= 1000:
        int_str = str(integer)
        chunks = list(splitbyx(int_str, 3))
        # Process each chunk with scale words
    else:
        # Process as simple hundreds
        digits = get_digits(integer)
        # Process individual digits
    
    # Convert components to strings safely
    result_parts = [to_s(part) for part in processed_parts]
    
    return " ".join(result_parts)

# Error handling with utilities
def safe_parse_currency(value):
    """Safely parse currency with error handling."""
    try:
        return parse_currency_parts(value)
    except (ValueError, TypeError) as e:
        # Handle parsing errors gracefully
        return 0, 0, False

Integration with Main Library

These utilities integrate seamlessly with the main num2words functionality:

# Internal usage in num2words function
def num2words(number, **kwargs):
    # String input handling
    if isinstance(number, strtype):
        number = converter.str_to_number(number)
    
    # Currency processing
    if kwargs.get('to') == 'currency':
        integer, cents, negative = parse_currency_parts(number)
        return converter.to_currency(number, **kwargs)
    
    # Standard number processing with utilities
    return converter.to_cardinal(number)

Error Handling

Utility functions provide robust error handling:

# Currency parsing errors
try:
    parse_currency_parts("invalid_number")
except ValueError as e:
    print(f"Invalid currency format: {e}")

# String conversion errors
try:
    result = to_s(complex_object)
except Exception as e:
    print(f"String conversion failed: {e}")

# Safe utility usage with fallbacks
def safe_split_number(num_str, chunk_size):
    """Safely split number string with error handling."""
    try:
        return list(splitbyx(num_str, chunk_size))
    except (ValueError, TypeError):
        # Fallback to character-based splitting
        return [num_str[i:i+chunk_size] for i in range(0, len(num_str), chunk_size)]

Install with Tessl CLI

npx tessl i tessl/pypi-num2words

docs

base-converter.md

currency-conversion.md

index.md

language-support.md

number-conversion.md

utility-functions.md

tile.json