or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-converter.mdcurrency-conversion.mdindex.mdlanguage-support.mdnumber-conversion.mdutility-functions.md

utility-functions.mddocs/

0

# Utility Functions

1

2

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.

3

4

## Capabilities

5

6

### Currency Processing Utilities

7

8

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

9

10

```python { .api }

11

def parse_currency_parts(value, is_int_with_cents=True):

12

"""

13

Parse currency value into integer and cents components.

14

15

Handles various input types and applies proper rounding for currency precision.

16

17

Parameters:

18

- value: int/float/Decimal/str - Currency value to parse

19

- is_int_with_cents: bool - Treat integer inputs as cents (default: True)

20

21

Returns:

22

tuple - (integer_part, cents_part, is_negative)

23

24

Raises:

25

ValueError - For invalid currency value formats

26

"""

27

```

28

29

**Usage Examples:**

30

31

```python

32

from num2words.currency import parse_currency_parts

33

34

# Float parsing with automatic rounding

35

integer, cents, negative = parse_currency_parts(42.567)

36

# (42, 57, False) - rounded to nearest cent

37

38

# Integer as cents (default behavior)

39

integer, cents, negative = parse_currency_parts(4250)

40

# (42, 50, False) - 4250 cents = 42.50 units

41

42

# Integer as whole units

43

integer, cents, negative = parse_currency_parts(42, is_int_with_cents=False)

44

# (42, 0, False) - 42 whole units, no cents

45

46

# String input parsing

47

integer, cents, negative = parse_currency_parts("42.50")

48

# (42, 50, False)

49

50

integer, cents, negative = parse_currency_parts("-123.45")

51

# (123, 45, True) - negative flag set

52

53

# Decimal precision handling

54

integer, cents, negative = parse_currency_parts(42.999)

55

# (43, 0, False) - rounds to nearest cent using ROUND_HALF_UP

56

57

# Edge cases

58

integer, cents, negative = parse_currency_parts(0.01)

59

# (0, 1, False) - minimum positive value

60

61

integer, cents, negative = parse_currency_parts(-0.50)

62

# (0, 50, True) - negative cents only

63

```

64

65

### Currency Form Utilities

66

67

Functions for manipulating currency form strings with prefixes and adjectives.

68

69

```python { .api }

70

def prefix_currency(prefix, base):

71

"""

72

Add prefix to currency forms for adjective support.

73

74

Parameters:

75

- prefix: str - Prefix to add (e.g., "European", "American")

76

- base: tuple - Base currency forms (singular, plural)

77

78

Returns:

79

tuple - Prefixed forms (prefixed_singular, prefixed_plural)

80

"""

81

```

82

83

**Usage Examples:**

84

85

```python

86

from num2words.currency import prefix_currency

87

88

# Add nationality adjectives

89

euro_forms = ('euro', 'euros')

90

prefixed_euro = prefix_currency('European', euro_forms)

91

# ('European euro', 'European euros')

92

93

dollar_forms = ('dollar', 'dollars')

94

prefixed_dollar = prefix_currency('American', dollar_forms)

95

# ('American dollar', 'American dollars')

96

97

# Use with currency conversion

98

# These prefixed forms are used when adjective=True in to_currency()

99

```

100

101

### Number String Processing Utilities

102

103

Functions for manipulating and splitting number strings.

104

105

```python { .api }

106

def splitbyx(n, x, format_int=True):

107

"""

108

Split number string into chunks of x digits.

109

110

Useful for processing large numbers in groups (e.g., thousands, millions).

111

112

Parameters:

113

- n: str - Number string to split

114

- x: int - Chunk size (number of digits per chunk)

115

- format_int: bool - Convert chunks to integers (default: True)

116

117

Yields:

118

int/str - Number chunks from left to right

119

"""

120

```

121

122

**Usage Examples:**

123

124

```python

125

from num2words.utils import splitbyx

126

127

# Split by thousands (3 digits)

128

number_str = "1234567890"

129

chunks = list(splitbyx(number_str, 3))

130

# [1, 234, 567, 890]

131

132

# Split with string preservation

133

chunks = list(splitbyx(number_str, 3, format_int=False))

134

# ['1', '234', '567', '890']

135

136

# Different chunk sizes

137

chunks = list(splitbyx("12345678", 4))

138

# [1234, 5678]

139

140

chunks = list(splitbyx("12345678", 2))

141

# [12, 34, 56, 78]

142

143

# Handle numbers shorter than chunk size

144

chunks = list(splitbyx("123", 5))

145

# [123] - single chunk when number is shorter

146

147

# Real-world usage in number processing

148

def process_large_number(num_str):

149

"""Example of using splitbyx for number word generation."""

150

chunks = list(splitbyx(num_str, 3)) # Split by thousands

151

# Process each chunk with appropriate scale (thousands, millions, etc.)

152

return chunks

153

```

154

155

### Digit Extraction Utilities

156

157

Functions for extracting and processing individual digits.

158

159

```python { .api }

160

def get_digits(n):

161

"""

162

Extract last 3 digits of number as reversed list.

163

164

Useful for processing hundreds, tens, and units places.

165

166

Parameters:

167

- n: int - Number to extract digits from

168

169

Returns:

170

list - List of last 3 digits in reverse order [units, tens, hundreds]

171

"""

172

```

173

174

**Usage Examples:**

175

176

```python

177

from num2words.utils import get_digits

178

179

# Basic digit extraction

180

digits = get_digits(123)

181

# [3, 2, 1] - units, tens, hundreds

182

183

digits = get_digits(45)

184

# [5, 4, 0] - units, tens, (zero) hundreds

185

186

digits = get_digits(7)

187

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

188

189

digits = get_digits(1000)

190

# [0, 0, 0] - last 3 digits of 1000

191

192

digits = get_digits(1234)

193

# [4, 3, 2] - last 3 digits: 234 reversed

194

195

# Usage in number word generation

196

def process_hundreds(n):

197

"""Example of using get_digits for word generation."""

198

units, tens, hundreds = get_digits(n)

199

200

words = []

201

if hundreds:

202

words.append(f"{digit_words[hundreds]} hundred")

203

if tens >= 2:

204

words.append(f"{tens_words[tens]}")

205

if units:

206

words.append(f"{digit_words[units]}")

207

elif tens == 1:

208

words.append(f"{teens_words[units]}")

209

elif units:

210

words.append(f"{digit_words[units]}")

211

212

return " ".join(words)

213

```

214

215

### Python Compatibility Utilities

216

217

Functions for maintaining compatibility between Python 2 and Python 3.

218

219

```python { .api }

220

def to_s(val):

221

"""

222

Convert value to string with Python 2/3 compatibility.

223

224

Handles unicode/str differences between Python versions.

225

226

Parameters:

227

- val: Any - Value to convert to string

228

229

Returns:

230

str/unicode - String representation appropriate for Python version

231

"""

232

```

233

234

**Usage Examples:**

235

236

```python

237

from num2words.compat import to_s

238

239

# Safe string conversion across Python versions

240

text = to_s(42) # "42"

241

text = to_s(42.5) # "42.5"

242

text = to_s("hello") # "hello"

243

244

# Handles unicode properly in both Python 2 and 3

245

unicode_text = to_s("café") # Proper encoding handling

246

247

# Used internally by converters for consistent string handling

248

def safe_word_join(words):

249

"""Example internal usage."""

250

return " ".join(to_s(word) for word in words)

251

```

252

253

### String Type Detection

254

255

Compatibility utilities for string type checking.

256

257

```python { .api }

258

# String type compatibility

259

strtype = basestring # Python 2

260

strtype = str # Python 3 (when basestring not available)

261

```

262

263

**Usage Examples:**

264

265

```python

266

from num2words.compat import strtype

267

268

# Type checking that works across Python versions

269

def is_string_input(value):

270

"""Check if input is a string type."""

271

return isinstance(value, strtype)

272

273

# Example usage in validation

274

def validate_input(value):

275

"""Validate input type for conversion."""

276

if is_string_input(value):

277

# Handle string input

278

return float(value)

279

elif isinstance(value, (int, float)):

280

# Handle numeric input

281

return value

282

else:

283

raise TypeError(f"Unsupported input type: {type(value)}")

284

```

285

286

### Decimal Processing Utilities

287

288

High-precision decimal operations used in currency conversion.

289

290

```python { .api }

291

# Decimal rounding modes

292

from decimal import ROUND_HALF_UP, Decimal

293

294

# Used internally for currency precision

295

def quantize_currency(value):

296

"""Round currency value to 2 decimal places."""

297

return Decimal(str(value)).quantize(

298

Decimal('.01'),

299

rounding=ROUND_HALF_UP

300

)

301

```

302

303

**Usage Examples:**

304

305

```python

306

from decimal import Decimal, ROUND_HALF_UP

307

308

# Precise currency rounding (used internally)

309

value = Decimal('42.567')

310

rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)

311

# Decimal('42.57')

312

313

# Handle edge cases in rounding

314

value = Decimal('42.565')

315

rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)

316

# Decimal('42.57') - rounds up at .5

317

318

value = Decimal('42.564')

319

rounded = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)

320

# Decimal('42.56') - rounds down below .5

321

```

322

323

### Internal Processing Helpers

324

325

Utilities used internally by the converter classes.

326

327

```python

328

# Number component processing

329

def split_currency_components(value):

330

"""Split currency value maintaining precision."""

331

if isinstance(value, int):

332

# Assume cents if integer

333

negative = value < 0

334

value = abs(value)

335

integer, cents = divmod(value, 100)

336

else:

337

# Handle float/Decimal with rounding

338

value = Decimal(str(value))

339

value = value.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)

340

negative = value < 0

341

value = abs(value)

342

integer, fraction = divmod(value, 1)

343

cents = int(fraction * 100)

344

345

return int(integer), cents, negative

346

347

# String cleaning and normalization

348

def normalize_number_string(num_str):

349

"""Clean and normalize number string input."""

350

# Remove common formatting characters

351

cleaned = num_str.replace(',', '').replace(' ', '')

352

353

# Handle negative signs

354

if cleaned.startswith('-'):

355

return '-', cleaned[1:]

356

else:

357

return '', cleaned

358

```

359

360

### Advanced Usage Examples

361

362

Combining utilities for custom number processing.

363

364

```python

365

from num2words.utils import splitbyx, get_digits

366

from num2words.currency import parse_currency_parts

367

from num2words.compat import to_s

368

369

def custom_number_processor(value):

370

"""Example of combining utilities for custom processing."""

371

372

# Parse as currency to get components

373

integer, cents, negative = parse_currency_parts(value)

374

375

# Process large integer part in chunks

376

if integer >= 1000:

377

int_str = str(integer)

378

chunks = list(splitbyx(int_str, 3))

379

# Process each chunk with scale words

380

else:

381

# Process as simple hundreds

382

digits = get_digits(integer)

383

# Process individual digits

384

385

# Convert components to strings safely

386

result_parts = [to_s(part) for part in processed_parts]

387

388

return " ".join(result_parts)

389

390

# Error handling with utilities

391

def safe_parse_currency(value):

392

"""Safely parse currency with error handling."""

393

try:

394

return parse_currency_parts(value)

395

except (ValueError, TypeError) as e:

396

# Handle parsing errors gracefully

397

return 0, 0, False

398

```

399

400

## Integration with Main Library

401

402

These utilities integrate seamlessly with the main num2words functionality:

403

404

```python

405

# Internal usage in num2words function

406

def num2words(number, **kwargs):

407

# String input handling

408

if isinstance(number, strtype):

409

number = converter.str_to_number(number)

410

411

# Currency processing

412

if kwargs.get('to') == 'currency':

413

integer, cents, negative = parse_currency_parts(number)

414

return converter.to_currency(number, **kwargs)

415

416

# Standard number processing with utilities

417

return converter.to_cardinal(number)

418

```

419

420

## Error Handling

421

422

Utility functions provide robust error handling:

423

424

```python

425

# Currency parsing errors

426

try:

427

parse_currency_parts("invalid_number")

428

except ValueError as e:

429

print(f"Invalid currency format: {e}")

430

431

# String conversion errors

432

try:

433

result = to_s(complex_object)

434

except Exception as e:

435

print(f"String conversion failed: {e}")

436

437

# Safe utility usage with fallbacks

438

def safe_split_number(num_str, chunk_size):

439

"""Safely split number string with error handling."""

440

try:

441

return list(splitbyx(num_str, chunk_size))

442

except (ValueError, TypeError):

443

# Fallback to character-based splitting

444

return [num_str[i:i+chunk_size] for i in range(0, len(num_str), chunk_size)]

445

```