home *** CD-ROM | disk | FTP | other *** search
- ###########################################################################
- #
- # File: numbers.icn
- #
- # Subject: Procedures to format and convert numbers
- #
- # Author: Ralph E. Griswold and Tim Korb
- #
- # Date: February 1, 1991
- #
- ###########################################################################
- #
- # These procedures format numbers in various ways:
- #
- # commas(s) inserts commas in s to separate digits into groups of
- # three.
- #
- # roman(i) converts s to Roman numerals.
- #
- # spell(i) spells out i in English.
- #
- # fix(i,j,w,d) formats i / j as a real (floating-point) number in
- # a field of width w with d digits to the right of
- # the decimal point, if possible. j defaults to 1,
- # w to 8, and d to 3. If w is less than 3 it is set
- # to 3. If d is less than 1, it is set to 1. The
- # function fails if j is 0 or if the number cannot
- # be formatted.
- #
- ############################################################################
-
- procedure commas(n)
- if *n < 4 then return n
- else return commas(left(n,*n - 3)) || map(",123","123",right(n,3))
- end
-
- # This procedure is based on a SNOBOL4 function written by Jim Gimpel.
- #
- procedure roman(n)
- local arabic, result
- static equiv
- initial equiv := ["","I","II","III","IV","V","VI","VII","VIII","IX"]
- integer(n) > 0 | fail
- result := ""
- every arabic := !n do
- result := map(result,"IVXLCDM","XLCDM**") || equiv[arabic + 1]
- if find("*",result) then fail else return result
- end
-
- procedure spell(n)
- local m
- n := integer(n) | stop(image(n)," is not an integer")
- if n <= 12 then return {
- "0zero,1one,2two,3three,4four,5five,6six,7seven,8eight,_
- 9nine,10ten,11eleven,12twelve," ? {
- tab(find(n))
- move(*n)
- tab(find(","))
- }
- }
- else if n <= 19 then return {
- spell(n[2] || "0") ?
- (if ="for" then "four" else tab(find("ty"))) || "teen"
- }
- else if n <= 99 then return {
- "2twen,3thir,4for,5fif,6six,7seven,8eigh,9nine," ? {
- tab(find(n[1]))
- move(1)
- tab(find(",")) || "ty" ||
- if n[2] ~= 0 then "-" || spell(n[2])
- }
- }
- else if n <= 999 then return {
- spell(n[1]) || " hundred" ||
- (if (m := n[2:0]) ~= 0 then " and " || spell(m) else "")
- }
- else if n <= 999999 then return {
- spell(n[1:-3]) || " thousand" ||
- (if (m := n[2:0]) ~= 0 then " and " || spell(m) else "")
- }
- else if n <= 999999999 then return {
- spell(n[1:-6]) || " million" ||
- (if (m := n[2:0]) ~= 0 then " and " || spell(m) else "")
- }
- else fail
- end
-
- procedure fix(i,j,w,d)
- local r, int, dec
-
- /j := 1
- /w := 8
- /d := 3
- if j = 0 then fail
- w <:= 3
- d <:= 1
- r := real(i) / j
-
- int := dec := "0" # prepare for small number
-
- if not(r < ("0." || repl("0", d - 1) || "1")) then { # formats as zero
- string(r) ? {
- if upto('eE') then fail # can't format
- if int := tab(find(".")) then {
- move(1)
- dec := tab(0)
- }
- }
- }
-
- if *int < w - d + 1 then int := right(int,w - d + 1)
-
- return int || "." || left(dec,d,"0")
-
- end
-