Documentation
¶
Overview ¶
Package numbers verbalizes the numbers found in text as English words.
It is a standalone engine: unlike the name-oriented manglers it does its own number-aware scanning (it must see the decimal points and digit-group separators that the general tokenizer elides), so it does not depend on a separate tokenizer. The parent mangling package reaches it through GoMangler.ConstName.
Entry points ¶
- NumberMangler rewrites every number in a string ("level 0.25 here" → "level one quarter here"). See NumberMangler.NumberWords for the full rules, and NumberMangler.AppendWords for the allocation-free variant.
- RuneNumber resolves a single Unicode numeral rune to its value ('½' → 0.5, 'Ⅶ' → 7).
- Roman renders an integer as a lowercase roman numeral (6 → "vi"), handy for compact sequence labels.
How numbers are recognized ¶
Integers become cardinals ("123" → "one hundred and twenty three"); a value in (-1, 1) matching a simple fraction becomes that fraction ("0.25" → "one quarter"); any other decimal is spelled digit-by-digit after "dot" ("3.14" → "three dot one four"); negatives are prefixed with "minus". Thousands separators (space, comma or underscore before exactly three digits) are reconstructed, and integers too large for int64 are spelled digit by digit so no input overflows.
Rendering honors the mangler options: WithNumberStripOne, WithNumberStripAnd, WithNumberDetectPrecision and WithSpecialNumbers.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NumberRune ¶
NumberRune is the default-options form of NumberMangler.NumberRune: it verbalizes a single Unicode numeral rune with no options applied. Build a NumberMangler and call its method when options matter.
func Roman ¶
Roman renders a positive integer as a lowercase roman numeral (e.g. 12 → "xii", 1994 → "mcmxciv").
It uses the standard subtractive notation (4 → "iv", not "iiii"; 9 → "ix", not "viiii"), which makes it a handy source of compact, human-readable sequence labels — nested loop indices, list markers, and the like: "i", "ii", "iii", "iv", "v", … Uppercase the result with strings.ToUpper if you need "IV".
It returns "" for n ≤ 0.
There is no upper bound: values above 3999 simply repeat "m" (4000 → "mmmm"), which is unambiguous if unconventional (we don't use the vinculum system for large numbers, as it requires non-ASCII characters).
func RuneNumber ¶
RuneNumber returns the numeric value of a Unicode numeral rune (categories No and Nl — e.g. '½' → 0.5, 'Ⅶ' → 7, '②' → 2) and whether r is such a numeral.
Decimal digits (Nd) and CJK ideographic numbers (Lo) are deliberately excluded. It lets a numeral rune verbalize through this engine ('½' → "one half") and lets the asciify tier render it as a plain number ('½' → "0.5"). Table in numerals.go.
Types ¶
type NumberMangler ¶
type NumberMangler struct {
// contains filtered or unexported fields
}
NumberMangler verbalizes the numbers found in text as English words: cardinals and common fractions, with digit-group (thousands) reconstruction.
It is a standalone engine: unlike the name-oriented manglers it does its own number-aware scanning (it must see decimal points and digit-group separators that the general tokenizer elides), so it does not depend on a separate tokenizer.
func MakeNumberMangler ¶
func MakeNumberMangler(opts ...NumberOption) NumberMangler
MakeNumberMangler returns a value NumberMangler.
func NewNumberMangler ¶
func NewNumberMangler(opts ...NumberOption) *NumberMangler
NewNumberMangler returns a pointer to a NumberMangler.
func (NumberMangler) AppendWords ¶
func (m NumberMangler) AppendWords(dst []byte, in string) []byte
AppendWords appends the english-words form of in (numbers verbalized, surrounding text verbatim) to dst and returns the extended slice.
This is the string-free sibling of NumberMangler.NumberWords.
The caller owns dst and may reuse it across calls, so bulk verbalization runs allocation-free, like so:
var scratch []byte
for _, s := range inputs {
scratch = m.AppendWords(scratch[:0], s)
use(scratch) // valid until the next AppendWords into scratch
}
func (NumberMangler) NumberRune ¶
func (m NumberMangler) NumberRune(r rune) string
NumberRune verbalizes a single Unicode numeral rune as English words ('½' → "one half", 'Ⅶ' → "seven", '②' → "two"), or returns "" when r is not a numeral rune (categories No and Nl; see RuneNumber).
It is the single-rune form of NumberMangler.NumberWords: it resolves the rune's value with RuneNumber and renders it directly, skipping the string scanner and the string(r) allocation that NumberWords(string(r)) would cost — this runs per numeral rune in the asciify pass.
Rendering honors the mangler's options (WithNumberStripOne etc.), so a numeral rune verbalizes consistently with the same value written as digits ('½' and "1/2"-style input agree under one mangler). Use the package-level NumberRune for a quick default-options rendering without a mangler.
func (NumberMangler) NumberWords ¶
func (m NumberMangler) NumberWords(in string) string
NumberWords rewrites every number found in a string as english words.
It leaves the surrounding text untouched, e.g. "10 11" => "ten eleven", "level 0.25 here" => "level one quarter here".
Multiple numbers are handled independently.
Each number is an optional sign followed by digits with an optional decimal point:
- integers become cardinals: "123" => "one hundred and twenty three";
- a value in (-1, 1) matching a simple fraction becomes that fraction: "0.25" => "one quarter", "0.1" => "one tenth", "0.75" => "three quarters";
- any other decimal is spelled digit-by-digit after "dot": "0.31456" => "zero dot three one four five six";
- negatives are prefixed with "minus".
Thousands separators are reconstructed: within a number, a space, comma or underscore followed by exactly three digits joins the group, so "1 234", "1,234" and "1_234" all become "one thousand two hundred and thirty four", while "1 2" stays two numbers ("one two") and "1;234" is not joined (";" is not a separator).
Registered special numbers (WithSpecialNumbers) are matched (within tolerance) ahead of everything else, so "3.1415" => "pi".
Rendering honors the mangler's options: WithNumberStripOne ("one hundred" => "hundred", "one tenth" => "tenth"), WithNumberStripAnd (drops the "and"), and WithNumberDetectPrecision (fraction and special-number tolerance).
type NumberOption ¶
type NumberOption func(numberOptions) numberOptions
NumberOption customizes the behavior of the NumberMangler.
func WithNumberDetectPrecision ¶
func WithNumberDetectPrecision(precision uint) NumberOption
WithNumberDetectPrecision sets the number of decimal places used when matching a value against known fractions and special numbers.
A higher precision distinguishes closer values (e.g. 0.333 from 1/3) at the cost of fewer fuzzy matches.
func WithNumberStripAnd ¶
func WithNumberStripAnd(strip bool) NumberOption
WithNumberStripAnd alters how NumberMangler.NumberWords renders numerals: whenever stripped the "and" in "one hundred and ten", etc is elided.
func WithNumberStripOne ¶
func WithNumberStripOne(strip bool) NumberOption
WithNumberStripOne alters how NumberMangler.NumberWords renders numerals: whenever stripped the "one" prefix in "one hundred", "one tenth", etc is elided.
func WithSpecialNumbers ¶
func WithSpecialNumbers(specials map[string]string) NumberOption
WithSpecialNumbers registers named numeric constants, matched (numerically, within the detection precision) ahead of cardinal/fraction rendering.
Example: WithSpecialNumbers(map[string]string{"3.1415": "pi", "2.718": "e"}) renders any number within tolerance of 3.1415 as "pi".