Spelling of ordinal numbers: Difference between revisions

Added FreeBASIC
No edit summary
(Added FreeBASIC)
 
(10 intermediate revisions by 6 users not shown)
Line 17:
 
 
Furthermore, the Americanshort versionscale ofnumbering numberssystem (i.e. 2,000,000,000 is two billion) will be used here.  [[wp:Long (asand opposedshort to the British).scales]]
 
'''2,000,000,000'''   is two billion,   ''not''   two milliard.
Line 39:
*   [[N'th]]
<br><br>
 
=={{header|ALGOL 68}}==
Assumes LONG INT is at least 64 bits, as in e.g., Algol 68G.
<syntaxhighlight lang="algol68">
BEGIN # construct number names from a number #
[]STRING units
= ( "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" );
[]STRING unit prefix
= ( "ten", "twen", "thir", "four", "fif", "six", "seven", "eigh", "nine" );
[]STRING singleth
= ( "first", "second", "third", "fourth", "fifth"
, "sixth", "seventh", "eighth", "nineth"
);
[]STRING power suffix
= ( "thousand", "million", "billion", "trillion", "quadrillion", "quintillion" );
# returns n converted to a number name, n must be 1-99 #
# if final is TRUE, the name will end in st, nd, rd, ... #
PROC two digits = ( INT n, BOOL final )STRING:
IF n < 10 THEN IF final THEN singleth[ n ] ELSE units[ n ] FI
ELIF n = 10 THEN IF final THEN "tenth" ELSE "ten" FI
ELIF n = 11 THEN IF final THEN "eleventh" ELSE "eleven" FI
ELIF n = 12 THEN IF final THEN "twelfth" ELSE "twelve" FI
ELIF n < 20 THEN unit prefix[ n - 10 ]
+ IF final THEN "teenth" ELSE "teen" FI
ELIF n MOD 10 = 0 THEN unit prefix[ n OVER 10 ]
+ IF final THEN "tieth" ELSE "ty" FI
ELSE unit prefix[ n OVER 10 ]
+ "ty "
+ IF final THEN singleth[ n MOD 10 ] ELSE units[ n MOD 10 ] FI
FI # two digits # ;
# returns n converted to a number name, n must be 1-999 #
# if final is TRUE, the name will end in st, nd, rd, ... #
PROC three digits = ( INT n, BOOL final )STRING:
IF n < 100
THEN two digits( n, final )
ELIF STRING hundreds = units[ n OVER 100 ] + " hundred";
INT ending = n MOD 100;
ending = 0
THEN IF final THEN hundreds + "th" ELSE hundreds FI
ELSE hundreds + " and " + two digits( ending, final )
FI # three digits # ;
# returns the "name" of n #
OP NAME = ( LONG INT n )STRING:
IF n < 0 THEN "minus " + NAME - n
ELIF n = 0 THEN "zeroth"
ELSE
# have a positive number to name #
LONG INT v := n;
STRING result := "";
INT power pos := 0;
WHILE v /= 0 DO
BOOL final component = power pos = 0;
INT v999 = SHORTEN ( v MOD 1000 );
IF v999 /= 0 THEN
STRING component := three digits( v999, final component );
IF power pos > 0 THEN
component +:= " " + power suffix[ power pos ];
IF final component THEN component +:= "th" FI
FI;
IF power pos = 0 AND v > 1000 AND v999 < 100 THEN
"and " +=: component
FI;
IF result /= "" THEN component +:= " " FI;
component +=: result
FI;
power pos +:= 1;
v OVERAB 1000
OD;
IF n MOD 1000 = 0 THEN result + "th" ELSE result FI
FI # NAME # ;
# additional operator to handle shorter integers #
OP NAME = ( INT n )STRING: NAME LENG n;
# additional operators to handle integers expressed in floating point #
OP NAME = ( LONG REAL n )STRING: NAME ENTIER n;
OP NAME = ( REAL n )STRING: NAME ENTIER n;
# task test cases #
[]LONG INT t = ( 1, 2, 3, 4, 5, 11, 65, 100, 101, 272, 23 456, 8 007 006 005 004 003 );
FOR n FROM LWB t TO UPB t DO
print( ( whole( t[ n ], -16 ), ": ", NAME t[ n ], newline ) )
OD
END
</syntaxhighlight>
{{out}}
<pre>
1: first
2: second
3: third
4: fourth
5: fifth
11: eleventh
65: sixty fifth
100: one hundredth
101: one hundred and first
272: two hundred and seventy second
23456: twenty three thousand four hundred and fifty sixth
8007006005004003: eight quadrillion seven trillion six billion five million four thousand and third
</pre>
 
=={{header|AutoHotkey}}==
Line 236 ⟶ 333:
7891233: seven million eight hundred ninety-one thousand two hundred thirty-third
8007006005004003: eight quadrillion seven trillion six billion five million four thousand third
</pre>
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
using System.Collections.Generic;
 
class SpellingOfOrdinalNumbers
{
private static readonly Dictionary<string, string> ordinalMap = new Dictionary<string, string>
{
{"one", "first"},
{"two", "second"},
{"three", "third"},
{"five", "fifth"},
{"eight", "eighth"},
{"nine", "ninth"},
{"twelve", "twelfth"}
};
 
static void Main(string[] args)
{
long[] tests = new long[] { 1, 2, 3, 4, 5, 11, 65, 100, 101, 272, 23456, 8007006005004003L };
foreach (long test in tests)
{
Console.WriteLine($"{test} = {ToOrdinal(test)}");
}
}
 
private static string ToOrdinal(long n)
{
string spelling = NumToString(n);
string[] split = spelling.Split(' ');
string last = split[split.Length - 1];
string replace;
if (last.Contains("-"))
{
string[] lastSplit = last.Split('-');
string lastWithDash = lastSplit[1];
string lastReplace;
if (ordinalMap.ContainsKey(lastWithDash))
{
lastReplace = ordinalMap[lastWithDash];
}
else if (lastWithDash.EndsWith("y"))
{
lastReplace = lastWithDash.Substring(0, lastWithDash.Length - 1) + "ieth";
}
else
{
lastReplace = lastWithDash + "th";
}
replace = lastSplit[0] + "-" + lastReplace;
}
else
{
if (ordinalMap.ContainsKey(last))
{
replace = ordinalMap[last];
}
else if (last.EndsWith("y"))
{
replace = last.Substring(0, last.Length - 1) + "ieth";
}
else
{
replace = last + "th";
}
}
split[split.Length - 1] = replace;
return string.Join(" ", split);
}
 
private static readonly string[] nums = new string[]
{
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
};
 
private static readonly string[] tens = new string[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
 
private static string NumToString(long n)
{
return NumToStringHelper(n);
}
 
private static string NumToStringHelper(long n)
{
if (n < 0)
{
return "negative " + NumToStringHelper(-n);
}
if (n <= 19)
{
return nums[n];
}
if (n <= 99)
{
return tens[n / 10] + (n % 10 > 0 ? "-" + NumToStringHelper(n % 10) : "");
}
string label = null;
long factor = 0;
if (n <= 999)
{
label = "hundred";
factor = 100;
}
else if (n <= 999999)
{
label = "thousand";
factor = 1000;
}
else if (n <= 999999999)
{
label = "million";
factor = 1000000;
}
else if (n <= 999999999999L)
{
label = "billion";
factor = 1000000000;
}
else if (n <= 999999999999999L)
{
label = "trillion";
factor = 1000000000000L;
}
else if (n <= 999999999999999999L)
{
label = "quadrillion";
factor = 1000000000000000L;
}
else
{
label = "quintillion";
factor = 1000000000000000000L;
}
return NumToStringHelper(n / factor) + " " + label + (n % factor > 0 ? " " + NumToStringHelper(n % factor) : "");
}
}
</syntaxhighlight>
{{out}}
<pre>
1 = first
2 = second
3 = third
4 = fourth
5 = fifth
11 = eleventh
65 = sixty-fifth
100 = one hundredth
101 = one hundred first
272 = two hundred seventy-second
23456 = twenty-three thousand four hundred fifty-sixth
8007006005004003 = eight quadrillion seven trillion six billion five million four thousand third
 
</pre>
 
Line 508 ⟶ 762:
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">Dim Shared small(19) As String*9 => { _
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", _
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", _
"sixteen", "seventeen", "eighteen", "nineteen" }
Dim Shared tens(9) As String*7 => { "", "", _
"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" }
Dim Shared illions(6) As String*12 => {"", _
" thousand", " million", " billion"," trillion", " quadrillion", " quintillion" }
Dim Shared irregularOrdinals(7, 1) As String*7 = { _
{"one", "first"}, {"two", "second"}, {"three", "third"}, {"five", "fifth"}, _
{"eight", "eighth"}, {"nine", "ninth"}, {"twelve", "twelfth"} }
 
Function spell(n As Integer) As String
Dim As String sx, ix, t = ""
Dim As Integer s, i, p
If n < 0 Then
t = "negative "
n = -n
End If
If n < 20 Then
t &= small(n)
Elseif n < 100 Then
t &= tens(n \ 10)
s = n Mod 10
If s > 0 Then t &= "-" & small(s)
Elseif n < 1000 Then
t &= small(n \ 100) & " hundred"
s = n Mod 100
If s > 0 Then t &= " " & spell(s)
Else
sx = ""
i = 0
While n > 0
p = n Mod 1000
n \= 1000
If p > 0 Then
ix = spell(p) & illions(i)
If sx <> "" Then ix &= " " & sx
sx = ix
End If
i += 1
Wend
t &= sx
End If
Return t
End Function
 
Function sayOrdinal(n As Integer) As String
Dim As String s = spell(n)
Dim As String lastWord = ""
Dim As Integer j, i = Len(s)
While i > 0 And Mid(s, i, 1) <> " " And Mid(s, i, 1) <> "-"
lastWord = Mid(s, i, 1) + lastWord
i -= 1
Wend
For j = 0 To Ubound(irregularOrdinals, 1)
If irregularOrdinals(j, 0) = lastWord Then
Return Left(s, i) + irregularOrdinals(j, 1)
End If
Next j
If Right(s, 1) = "y" Then
Return Left(s, Len(s) - 1) + "ieth"
Else
Return s + "th"
End If
End Function
 
Dim As Integer t(0 To ...) = { 1, 2, 3, 4, 5, 11, 65, 100, 101, 272, _
23456, 8007006005004003, 123, 00123.0, 1.23E2 }
For n As Integer = 0 To Ubound(t)
Print sayOrdinal(t(n))
Next n
 
Sleep</syntaxhighlight>
{{out}}
<pre>first
second
third
fourth
fifth
eleventh
sixty-fifth
one hundredth
one hundred first
two hundred seventy-second
twenty-three thousand four hundred fifty-sixth
eight quadrillion seven trillion six billion five million four thousand third
one hundred twenty-third
one hundred twenty-third
one hundred twenty-third</pre>
 
=={{header|Go}}==
Line 836 ⟶ 1,183:
23456 = twenty-three thousand four hundred fifty-sixth
8007006005004003 = eight quadrillion seven trillion six billion five million four thousand third
</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq and fq, the Go implementations'''
 
One point of interest in the following is that the program checks not
only that its integer input is within the scope of the program, but
also that it is within the capability of the C or Go platform.
In particular, `check_ok` checks for the platform's precision of
integer arithmetic.
 
For further remarks on this point, see the comments that
are included in the test data.
<syntaxhighlight lang=jq>
# integer division for precision when using gojq
def idivide($j):
. as $i
| ($i % $j) as $mod
| ($i - $mod) / $j ;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
 
def small:
["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
 
def tens:
["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
 
# Up to 1e63 (vigintillion)
def illions:
["", " thousand", " million", " billion"," trillion", " quadrillion", " quintillion",
" sextillion", " septillion", " octillion", " nonillion", " decillion", " undecillion",
" duodecillion", " tredecillion", " quattuordecillion", " quindecillion",
" sexdecillion", " septendecillion", " octadecillion", " novemdecillion",
" vigintillion"
];
 
def illions($i):
if $i >= (illions|length) then "\($i * 3) zeros is beyond the scope of this exercise" | error
else illions[$i]
end;
 
def irregularOrdinals: {
"one": "first",
"two": "second",
"three": "third",
"five": "fifth",
"eight": "eighth",
"nine": "ninth",
"twelve": "twelfth"
};
 
def check_ok:
def ieee754:
9007199254740993==9007199254740992;
if ieee754
then if (. > 0 and (. + 1) == .) or (. < 0 and (. - 1) == .)
then "The number \(.) is too large for this platform" | error
else .
end
else .
end;
# error courtesy of illions/1 if order of magnitude is too large
def say:
check_ok
| { t: "", n: .}
| if .n < 0 then .t = "negative " | .n *= -1 else . end
| if .n < 20
then .t += small[.n]
elif .n < 100
then .t += tens[.n | idivide(10)]
| .s = .n % 10
| if .s > 0 then .t += "-" + small[.s] else . end
elif .n < 1000
then .t += small[.n | idivide(100)] + " hundred"
| .s = .n % 100
| if .s > 0 then .t += " " + (.s|say) else . end
else .sx = ""
| .i = 0
| until (.n <= 0;
.p = .n % 1000
| .n = (.n | idivide(1000))
| if .p > 0
then .ix = (.p|say) + illions(.i)
| if .sx != "" then .ix += " " + .sx else . end
| .sx = .ix
else .
end
| .i += 1 )
| .t += .sx
end
| .t ;
 
def sayOrdinal:
{n: ., s: say}
| .r = (.s | explode | reverse | implode)
| .i1 = (.r|index(" "))
| if .i1 then .i1 = (.s|length) - 1 - .i1 else . end
| .i2 = (.r|index("-"))
| if .i2 then .i2 = (.s|length) - 1 - .i2 else . end
# Set .i to 0 iff there was no space or hyphen:
| .i = (if .i1 or .i2 then 1 + ([.i1,.i2] | max) else 0 end)
# Now s[.i:] is the last word:
| irregularOrdinals[.s[.i:]] as $x
| if $x then .s[:.i] + $x
elif .s | endswith("y")
then .s[:-1] + "ieth"
else .s + "th"
end;
 
# Sample inputs
(1, 2, 3, 4, 5, 11, 65, 100, 101, 272, 23456,
8007006005004003,
9007199254740991,
2e12,
9007199254740993, # too large for jq
# 1e63 is vigintillion so gojq should be able to handle 999 * 1e63
999000000000000000000000000000000000000000000000000000000000000000,
# ... but not 1000 vigintillion
1000000000000000000000000000000000000000000000000000000000000000000
)
| "\(lpad(10)) => \(sayOrdinal)"
</syntaxhighlight>
{{output}}
The output using gojq is shown first. The tail of the output
using jq is then shown to illustrate what happens when the program
determines the given integer is too large for jq's built-in support
for integer arithmetic.
 
'''Using gojq'''
<pre>
1 => first
2 => second
3 => third
4 => fourth
5 => fifth
11 => eleventh
65 => sixty-fifth
100 => one hundredth
101 => one hundred first
272 => two hundred seventy-second
23456 => twenty-three thousand four hundred fifty-sixth
8007006005004003 => eight quadrillion seven trillion six billion five million four thousand third
9007199254740991 => nine quadrillion seven trillion one hundred ninety-nine billion two hundred fifty-four million seven hundred forty thousand nine hundred ninety-first
2000000000000 => two trillionth
9007199254740993 => nine quadrillion seven trillion one hundred ninety-nine billion two hundred fifty-four million seven hundred forty thousand nine hundred ninety-third
999000000000000000000000000000000000000000000000000000000000000000 => nine hundred ninety-nine vigintillionth
gojq: error: 66 zeros is beyond the scope of this exercise
</pre>
'''Tail of output using the C implementation'''
<pre>
2000000000000 => two trillionth
jq: error (at <unknown>): The number 9007199254740992 is too large for this platform
</pre>
 
=={{header|Julia}}==
This makes use of code posted on this site by MichaeLeroy for a similar task at https://rosettacode.org/wiki/[[Number_names#Julia]]. The function num2text is used (but not included here) as posted from that location.
<syntaxhighlight lang="julia">
const irregular = Dict("one" => "first", "two" => "second", "three" => "third", "five" => "fifth",
Line 1,480 ⟶ 1,986:
1.23e2 => one hundred and twenty-third
</pre>
 
=={{header|Quackery}}==
 
<code>name$</code> is defined at [[Number names#Quackery]].
 
<code>switch</code>, <code>case</code>, and <code>otherwise</code> are defined at [[Metaprogramming#Quackery]].
 
<syntaxhighlight lang="Quackery"> [ name$
dup -2 split nip
[ switch
$ "ne" case
[ -3 split drop
$ "first" join ]
$ "wo" case
[ -3 split drop
$ "second" join ]
$ "ee" case
[ -3 split drop
$ "ird" join ]
$ "ve" case
[ -2 split drop
$ "fth" join ]
$ "ht" case
[ $ "h" join ]
$ "ty" case
[ -1 split drop
$ "ieth" join ]
otherwise
[ $ "th" join ] ] ] is nameth$ ( n --> $ )
 
' [ 1 2 3 4 5 11 65 100 101 272 23456 8007006005004003 ]
witheach
[ dup echo say " = " nameth$ echo$ cr ]</syntaxhighlight>
 
{{out}}
 
<pre>1 = first
2 = second
3 = third
4 = fourth
5 = fifth
11 = eleventh
65 = sixty fifth
100 = one hundredth
101 = one hundred and first
272 = two hundred and seventy second
23456 = twenty three thousand and four hundred and fifty sixth
8007006005004003 = eight quadrillion, seven trillion, six billion, five million, four thousand and third</pre>
 
=={{header|Raku}}==
Line 2,180 ⟶ 2,734:
one hundred and twenty-third</pre>
 
=={{header|V (Vlang)}}==
{{trans|go}}
As with the Kotlin solution, this uses the output of <code>say</code> from the
[[Number_names#Go|Number_names]] task.
<syntaxhighlight lang="v (vlang)">fn main() {
for n in [i64(1), 2, 3, 4, 5, 11, 65, 100, 101, 272, 23456, 8007006005004003,
] {
Line 2,291 ⟶ 2,845:
 
Note that it is not safe to use this script for numbers with an absolute magnitude >= 2^53 as integers cannot be expressed exactly by Wren's Num type beyond that limit.
<syntaxhighlight lang="ecmascriptwren">var small = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven",
"twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
 
2,130

edits