# Numerals

This program takes a number and calculate it’s linguistic numeral.
The number $3$ returns the numeral $\text{three}$, $58$ returns $\text{fifty-eight}$ and $31415.926535$ returns $\text{thirty-one thousand four hundred fifteen point nine two six five three five}$.

# Python 2.7.7 Code
# Jonathan Frech 24th of May , 2016
#         edited 17th of June, 2016
#         edited 29th of June, 2017
#         * fixed spelling of 'forty'
#         * (In the post's image you can
#           still see the incorrect version.)
#         * Errare humanum est.

# import needed modules
import re

# get three digit's name
def section(n):
# variables
name = []

# in case it is zero
if n == 0:
return "zero"

# hundreds
if n > 99:
name.append(["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"][int(n/100)])
name.append("hundred")
n -= int(n/100)*100

# special number names
if n > 10 and n < 20: name.append(["eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"][n - 11]) return join(name) # tens if n > 9:
name.append(["", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"][int(n/10)])
name.append("-")
n -= int(n/10)*10
if n == 0:
name.pop(-1)

# ones
if n > 0:
name.append(["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"][n])

# return joined name
return join(name)

# joins the name list together
def join(name):
# variables
n = ""

for _ in name:
if _ != "":
n += " " + _

# for example 'fifty-five' instead of 'fifty - five'
n = re.sub("\ \-\ ", "-", n)

# remove space at the end
n = n[1:len(n)]

# special zero case
if n == "":
n = "zero"

# return joined name
return n

# get n's name
def name(n):
# variables
name = []

# special cases
global cases
if n in cases:
return cases[n]

# remove zeros at the front
n = re.sub("^0+", "0", n)

# check for negative numbers
if n[0] == "-":
# split off the minus sign
n = n[1:len(n)]

# add negativity to the name
name.append("minus")

# check for floats
f = None
if "." in n:
_ = re.split("\.", n)
n = _[0]
f = _[1]

# make the number's length a multiple of three
while len(n)%3 != 0:
n = "0" + n

# go through pairs of three and determine names
for _ in range(0, len(n)/3):
if int(n[(_*3):(_*3+3)]) != 0:
name.append(section(int(n[(_*3):(_*3+3)])))
powers = ["", "", "thousand", "million", "billion", "trillion", "quadrillion"]
if (len(n)/3-_) >= len(powers):
name.append("e" + str(3*(len(n)/3-_-1)))
else:
name.append(powers[len(n)/3-_])

# add the number's float part
if f:
name.append("point")
for _ in f:
name.append(["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"][int(_)])

# return joined name
return join(name)

# check if n even is a number
def check(n):
# number is a float
flt = False

# special cases
global cases
if n in cases:
return True

# go through number
for _ in range(0, len(n)):

# at first place there can be a minus sign
if n[_] == "-":
if _ != 0:
return False

# number could be a float (but not twice!)
elif n[_] == ".":
if flt:
return False
else:
flt = True

# numbers in base ten consist of ten different digits
else:
if n[_] not in "0123456789":
return False

# number is fine
return True

print "================="
print " N U M E R A L S "
print "================="
print ""

# special cases
global cases
cases = {"":""}
cases = {
"pi" : name("3.1415") + " and so on...",
"tau": name("6.2831") + " and so on...",
"e"  : name("2.7182") + " and so on...",
"phi": name("1.6180") + " and so on..."
}

# main loop
while True:
# get input
n = raw_input("> ")

# check input
if check(n):
print name(n)
else:
print "'" + n + "' is not a number..."