Skip to content

bug: num_to_thaiword: เอ็ด rule broken for millions block, and missing float support #1460

Description

@Warit-Yuv

Description

The num_to_thaiword function has a bug in the เอ็ด (one's-place) rule when a number has a digit 1 at the end of the millions block but there's a more significant digit before it. The เอ็ด rule only checks the very end of the output string, so it misses cases where "หนึ่ง" appears before "ล้าน" in the middle.

For example:

>>> from pythainlp.util import num_to_thaiword
>>> num_to_thaiword(101000000)
'หนึ่งร้อยหนึ่งล้าน'
# Incorrect, Should be 'หนึ่งร้อยเอ็ดล้าน'

Compare with numbers under 1 million where the เอ็ด rule works correctly:

>>> num_to_thaiword(101)
'หนึ่งร้อยเอ็ด'  # correct

This inconsistency shows the bug only affects the millions block.

Additionally, there is no function to convert floating-point numbers to Thai text. num_to_thaiword only accepts integers.

Expected results

  1. num_to_thaiword should correctly apply the เอ็ด rule to each 6-digit block independently.
  2. A new function num_to_thaiword_float should accept floats, read the decimal point as "จุด", and read each digit after the decimal individually.

Current results

>>> from pythainlp.util import num_to_thaiword
>>> num_to_thaiword(101000000)
'หนึ่งร้อยหนึ่งล้าน'

Steps to reproduce

from pythainlp.util import num_to_thaiword
## problematic case
print(num_to_thaiword(101000000))
# Expected: หนึ่งร้อยเอ็ดล้าน
# Actual:   หนึ่งร้อยหนึ่งล้าน
print(num_to_thaiword(501741221))
# Expected: ห้าร้อยเอ็ดล้านเจ็ดแสนสี่หมื่นหนึ่งพันสองร้อยยี่สิบเอ็ด
# Actual:   ห้าร้อยหนึ่งล้านเจ็ดแสนสี่หมื่นหนึ่งพันสองร้อยยี่สิบเอ็ด

## current passed case
print(num_to_thaiword(111000000))
# Expected: หนึ่งร้อยสิบเอ็ดล้าน
# Actual:   หนึ่งร้อยสิบเอ็ดล้าน (OK -- no 1 at block's end)

PyThaiNLP version

PyThaiNLP version: Latest dev/main

Python version

Python version: 3.9+, 3.14.3

Operating system and version

Window 11

More info

No response

Possible solution

Rewrite num_to_thaiword to process numbers in blocks of 6 digits (right-to-left), applying the เอ็ด rule independently within each block, plus a global trailing check. Add num_to_thaiword_float that reuses num_to_thaiword for the integer part and reads decimal digits individually after "จุด".

Files

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions