Skip to content

fix: ordinal_num returns '1.0st' for float 1.0 instead of '1st'#666

Open
gaoflow wants to merge 1 commit into
savoirfairelinux:masterfrom
gaoflow:fix/ordinal-num-float-value
Open

fix: ordinal_num returns '1.0st' for float 1.0 instead of '1st'#666
gaoflow wants to merge 1 commit into
savoirfairelinux:masterfrom
gaoflow:fix/ordinal-num-float-value

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown

Bug

num2words(1.0, to='ordinal_num') returns '1.0st' instead of '1st'.
The same problem affects every language that implements to_ordinal_num.

>>> num2words(1.0, lang='en', to='ordinal_num')
'1.0st'   # wrong
>>> num2words(2.0, lang='de', to='ordinal_num')
'2.0.'    # wrong
>>> num2words(1.0, lang='fr', to='ordinal_num')
'1.0er'   # wrong

Root cause

verify_ordinal accepts floats that equal their integer value (1.0 == int(1.0)),
so non-integer floats are correctly rejected while integer-valued floats pass through.
However, every to_ordinal_num implementation then converts value to a string with
str(value) or "%s" % value, which for 1.0 yields "1.0", embedding the decimal
point in the result.

Fix

Cast integer-valued floats to int inside num2words() before dispatching to the
language converter, for to='ordinal' and to='ordinal_num'. This fixes all language
implementations in one place without touching every language module.

# Before (wrong)
num2words(1.0, lang='en', to='ordinal_num')  # '1.0st'
num2words(2.0, lang='en', to='ordinal_num')  # '2.0nd'
num2words(21.0, lang='de', to='ordinal_num')  # '21.0.'

# After (correct)
num2words(1.0, lang='en', to='ordinal_num')  # '1st'
num2words(2.0, lang='en', to='ordinal_num')  # '2nd'
num2words(21.0, lang='de', to='ordinal_num')  # '21.'

Non-integer floats (1.5) still raise TypeError as before.

num2words(1.0, to='ordinal_num') returned '1.0st' instead of '1st'
because verify_ordinal accepts floats equal to their int value but each
language's to_ordinal_num used str() on the raw float, embedding the
decimal point in the result. The same bug affected to_ordinal_num in
all ~20 language implementations.

Fix by casting to int in the num2words dispatcher when the conversion
type is 'ordinal' or 'ordinal_num' and the value is a float that equals
its integer truncation. This restores correct results in a single place
without touching every language module.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant