41 lines
1.3 KiB
Crystal
41 lines
1.3 KiB
Crystal
struct Int
|
|
THOU_PREFIXES = %w(undec dec non oct sept sext quint quadr tr b m)
|
|
.map(&.+("illion")) + ["thousand", ""]
|
|
TENS = ["", ""] + %w(twen thir for fif six seven eigh nine).map &.+("ty")
|
|
ONES = [""] + %w(one two three four five six seven eight nine ten) +
|
|
%w(eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen)
|
|
def to_words
|
|
raise "Number to big to express in words" unless self.abs <= Int128::MAX
|
|
return "zero" if self == 0
|
|
String.build do |s|
|
|
n = self
|
|
if n < 0
|
|
s << "negative "
|
|
n = n.abs
|
|
end
|
|
ths = Array(Int128).new(THOU_PREFIXES.size, 0)
|
|
(0...ths.size).reverse_each do |idx|
|
|
n, ths[idx] = n.divmod(1000)
|
|
end
|
|
ths.zip(THOU_PREFIXES).each do |th, pref|
|
|
next if th == 0
|
|
hundreds, rest = th.divmod 100
|
|
s << ONES[hundreds] << " hundred " if hundreds > 0
|
|
if rest < 20
|
|
s << ONES[rest] << " " if rest > 0
|
|
else
|
|
tens, ones = rest.divmod 10
|
|
s << TENS[tens]
|
|
s << "-" << ONES[ones] if ones > 0
|
|
s << " "
|
|
end
|
|
s << pref << " " if pref != ""
|
|
end
|
|
s.chomp! 32u8
|
|
end
|
|
end
|
|
end
|
|
|
|
[0, 4, 6, 11, 75, -164, 1234, 9_876_543_209, Int128::MAX, 101010101010101].each do |n|
|
|
print " ", n, ": ", n.to_words, "\n"
|
|
end
|