Number names: Difference between revisions

no edit summary
m (→‎{{header|Phix}}: builtins\ordinal.e note)
No edit summary
Line 527:
2010: two thousand and ten
</pre>
 
=={{header|AppleScript}}==
 
With AppleScript's ability to access some of macOS's Objective-C frameworks, it's possible to get the job done with a single line:
 
<lang applescript>use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
 
on numberToWords(n)
return (current application's class "NSNumberFormatter"'s localizedStringFromNumber:(n) numberStyle:(current application's NSNumberFormatterSpellOutStyle)) as text
end numberToWords
 
numberToWords(-3.6028797018963E+10)
--> "minus thirty-six billion twenty-eight million seven hundred ninety-seven thousand eighteen point nine six three"</lang>
 
NSNumberFormatter supports several natural languages and by default uses the one set for the user on the host machine. However, its English is limited to US English, so there are no "and"s in the results.
 
Vanilla AppleScript can be more flexible if you're prepared to write the code. The following script, like the ASObjC one above, returns short-scale number names (which are easier to code anyway) and includes "and"s by default. However an optional parameter <code>without ands</code> can be used in the call if you'd prefer not to have them. Alternatively, changing the <code>true</code> in the top line of the handler to <code>false</code> will ''omit'' "and"s by default and calls will have to include <code>with ands</code> to get them.
 
Both scripts can display strange results with numbers that are at the extreme limits of their floating-point resolution.
 
<lang applescript>-- Parameters:
-- n: AppleScript integer or real.
-- ands (optional): boolean. Whether to include "and"s in the result. Default: true.
on numberToEnglish from n given ands:usingAnd : true
-- Script object containing the word lists and a recursive subhandler.
script o
property unitsAndTeens : {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", ¬
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
property tens : {missing value, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}
property landmarks : {"thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion"}
property collector : {} -- Words collected here.
-- Recursive subhandler for the integer part of the number.
on parseInt(n, landmarkNo)
-- Recursively work to the "front" of the integer "three digits" at a time.
if (n > 999) then parseInt(n div 1000, landmarkNo + 1)
-- Deal with each "three-digit" value on the way back.
set hundredsTensAndUnits to n mod 1000
-- Firstly the hundreds, if any. They'll only be single digits.
if (hundredsTensAndUnits > 99) then
set end of my collector to item (hundredsTensAndUnits div 100) of unitsAndTeens
set end of my collector to "hundred"
end if
-- Then the tens and units together, according to whether they require single words, hyphenated words or none.
set tensAndUnits to n mod 100
if (tensAndUnits > 0) then
-- Insert the word "and" if enabled and appropriate.
if ((usingAnd) and ¬
((collector ends with "hundred") ¬
or (collector ends with "thousand") ¬
or ((landmarkNo is 0) and (collector is not {})))) then ¬
set end of my collector to "and"
if (tensAndUnits < 20) then
set end of my collector to item tensAndUnits of my unitsAndTeens
else
set units to tensAndUnits mod 10
if (units > 0) then
set end of my collector to item (tensAndUnits div 10) of my tens & ("-" & item units of my unitsAndTeens)
else
set end of my collector to item (tensAndUnits div 10) of my tens
end if
end if
end if
-- Insert the "landmark" word for this point in the number, if applicable.
if ((hundredsTensAndUnits > 0) and (landmarkNo > 0)) then set end of my collector to item landmarkNo of my landmarks
end parseInt
end script
-- Main handler code.
-- Adjust for a negative if required.
if (n < 0) then
set end of o's collector to "minus"
set n to -n
end if
-- Deal with the integer part of the number first. Special-case zero, but otherwise parse.
if (n div 1 is 0) then
set end of o's collector to "zero"
else
tell o to parseInt(n div 1, 0)
end if
-- Deal with any fractional part, working forwards from the decimal point. (Vulnerable to floating-point inaccuracy at extreme lengths.)
if (n mod 1 > 0.0) then
set end of o's collector to "point"
-- Shift each fractional digit into the units position and read it off as an integer.
set n to n * 10
repeat
set units to n mod 10 div 1
if (units is 0) then
set end of o's collector to "zero"
else
set end of o's collector to item (units div 1) of o's unitsAndTeens
end if
set n to n * 10.0
if (n mod 10 is 0.0) then exit repeat
end repeat
end if
-- Coerce the assembled words to a single text.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to space
set English to o's collector as text
set AppleScript's text item delimiters to astid
return English
end numberToEnglish
 
numberToEnglish from -3.6028797018963E+10
--> "minus thirty-six billion twenty-eight million seven hundred and ninety-seven thousand and eighteen point nine six three"
numberToEnglish from -3.6028797018963E+10 without ands
--> "minus thirty-six billion twenty-eight million seven hundred ninety-seven thousand eighteen point nine six three"</lang>
 
=={{header|Applesoft BASIC}}==
557

edits