Использование Ruby конвертирует числа в слова?
Как преобразовать числа в слова в ruby?
Я знаю, что где-то есть драгоценный камень. Попытка реализовать его без драгоценного камня. Мне просто нужны числа для слов на английском языке для целых чисел. Нашел это, но это очень грязно. Если у вас есть какие-либо идеи о том, как реализовать более чистые решения для чтения, пожалуйста, поделитесь ими.
http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/
Вот о чем я работаю. Но есть проблема с реализацией масштабов. Код по-прежнему беспорядок. Я надеюсь сделать его более читаемым, когда он будет функционировать должным образом.
class Numberswords
def in_words(n)
words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
17=>"seventeen", 18=>"eighteen",19=>"nineteen",
20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
scale = [000=>"",1000=>"thousand",1000000=>" million",1000000000=>" billion",1000000000000=>" trillion", 1000000000000000=>" quadrillion"]
if words_hash.has_key?(n)
words_hash[n]
#still working on this middle part. Anything above 999 will not work
elsif n>= 1000
print n.to_s.scan(/.{1,3}/) do |number|
print number
end
#print value = n.to_s.reverse.scan(/.{1,3}/).inject([]) { |first_part,second_part| first_part << (second_part == "000" ? "" : second_part.reverse.to_i.in_words) }
#(value.each_with_index.map { |first_part,second_part| first_part == "" ? "" : first_part + scale[second_part] }-[""]).reverse.join(" ")
elsif n <= 99
return [words_hash[n - n%10],words_hash[n%10]].join(" ")
else
words_hash.merge!({ 100=>"hundred" })
([(n%100 < 20 ? n%100 : n.to_s[2].to_i), n.to_s[1].to_i*10, 100, n.to_s[0].to_i]-[0]-[10])
.reverse.map { |num| words_hash[num] }.join(" ")
end
end
end
#test code
test = Numberswords.new
print test.in_words(200)
Ответы
Ответ 1
Я принимаю это
def in_words(int)
numbers_to_name = {
1000000 => "million",
1000 => "thousand",
100 => "hundred",
90 => "ninety",
80 => "eighty",
70 => "seventy",
60 => "sixty",
50 => "fifty",
40 => "forty",
30 => "thirty",
20 => "twenty",
19=>"nineteen",
18=>"eighteen",
17=>"seventeen",
16=>"sixteen",
15=>"fifteen",
14=>"fourteen",
13=>"thirteen",
12=>"twelve",
11 => "eleven",
10 => "ten",
9 => "nine",
8 => "eight",
7 => "seven",
6 => "six",
5 => "five",
4 => "four",
3 => "three",
2 => "two",
1 => "one"
}
str = ""
numbers_to_name.each do |num, name|
if int == 0
return str
elsif int.to_s.length == 1 && int/num > 0
return str + "#{name}"
elsif int < 100 && int/num > 0
return str + "#{name}" if int%num == 0
return str + "#{name} " + in_words(int%num)
elsif int/num > 0
return str + in_words(int/num) + " #{name} " + in_words(int%num)
end
end
end
puts in_words(4) == "four"
puts in_words(27) == "twenty seven"
puts in_words(102) == "one hundred two"
puts in_words(38_079) == "thirty eight thousand seventy nine"
puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"
Ответ 2
Считаете ли вы "гуманизировать"?
https://github.com/radar/humanize
Ответ 3
Вы также можете использовать to_words gem.
Этот Gem преобразует целые числа в слова.
например.
1.to_words # one ,
100.to_words # one hundred ,
101.to_words # one hundred and one
Он также преобразует отрицательные числа.
Ответ 4
Я вижу, что вы ищете, и вы можете проверить этот пост StackOverflow: Числовые реверсивные преобразования для английского текста
Здесь кратко:
Нет, вам нужно написать функцию самостоятельно. Самое близкое к чему вы хотите number_to_human, но это не конвертирует 1 в 1.
Вот некоторые URL-адреса, которые могут быть полезны:
http://codesnippets.joyent.com/posts/show/447 http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/ http://deveiate.org/projects/Linguistics/
Ответ 5
Простой ответ используйте humanize
gem, и вы получите желаемый результат
require 'humanize'
1.humanize #=> 'one'
345.humanize #=> 'three hundred and forty-five'
1723323.humanize #=> 'one million, seven hundred and twenty-three thousand, three hundred and twenty-three'
Если вы используете это в рельсах, вы можете напрямую использовать это
Ответ 6
Я не совсем уверен, если это сработает для вас. Метод можно назвать так.
n2w(33123) {|i| puts i unless i.to_s.empty?}
Вот метод (я его не тестировал полностью. Я думаю, что он работает до миллиона. Код уродлив, есть много возможностей для повторного факторинга.)
def n2w(n)
words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
17=>"seventeen", 18=>"eighteen",19=>"nineteen",
20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
scale = {3=>"hundred",4 =>"thousand",6=>"million",9=>"billion"}
if words_hash.has_key?n
yield words_hash[n]
else
ns = n.to_s.split(//)
while ns.size > 0
if ns.size == 2
yield("and")
yield words_hash[(ns.join.to_i) - (ns.join.to_i)%10]
ns.shift
end
if ns.size > 4
yield(words_hash[(ns[0,2].join.to_i) - (ns[0,2].join.to_i) % 10])
else
yield(words_hash[ns[0].to_i])
end
yield(scale[ns.size])
ns.shift
end
end
end
Ответ 7
def subhundred number
ones = %w{zero one two three four five six seven eight nine
ten eleven twelve thirteen fourteen fifteen
sixteen seventeen eighteen nineteen}
tens = %w{zero ten twenty thirty **forty** fifty sixty seventy eighty ninety}
subhundred = number % 100
return [ones[subhundred]] if subhundred < 20
return [tens[subhundred / 10]] if subhundred % 10 == 0
return [tens[subhundred / 10], ones[subhundred % 10]]
end
def subthousand number
hundreds = (number % 1000) / 100
tens = number % 100
s = []
s = subhundred(hundreds) + ["hundred"] unless hundreds == 0
s = s + ["and"] unless hundreds == 0 or tens == 0
s = s + [subhundred(tens)] unless tens == 0
end
def decimals number
return [] unless number.to_s['.']
digits = number.to_s.split('.')[1].split('').reverse
digits = digits.drop_while {|d| d.to_i == 0} . reverse
digits = digits.map {|d| subhundred d.to_i} . flatten
digits.empty? ? [] : ["and cents"] + digits
end
def words_from_numbers number
steps = [""] + %w{thousand million billion trillion quadrillion quintillion sextillion}
result = []
n = number.to_i
steps.each do |step|
x = n % 1000
unit = (step == "") ? [] : [step]
result = subthousand(x) + unit + result unless x == 0
n = n / 1000
end
result = ["zero"] if result.empty?
result = result + decimals(number)
result.join(' ').strip
end
def words_from_numbers(number)
ApplicationHelper.words_from_numbers(number)
end
Ответ 8
Вот как я решил решить проблему, используя несколько более мелких методов для обработки решения. Надеюсь, это поможет!
module WordsModule
def in_words
if self == 0
return "zero"
elsif self > 999_999_999_999
return trillions(self)
elsif self > 999_999_999
return billions(self)
elsif self > 999_999
return millions(self)
elsif self > 999
return thousands(self)
elsif self > 99
return hundreds(self)
elsif self > 9
return "#{tens(self)}"
else
return "#{single(self)}"
end
end
private
def trillions(number)
if number.between?(100_000_000_000_000, 999_999_999_999_999)
if number % 1_000_000_000_000 == 0
"#{hundreds(number/1_000_000_000_000)} trillion"
else
"#{hundreds(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
end
elsif number.between?(10_000_000_000_000, 99_999_999_999_999)
if number % 1_000_000_000_000 == 0
"#{tens(number/1_000_000_000_000)} trillion"
else
"#{tens(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
end
elsif number.between?(1_000_000_000_000, 9_999_999_999_999)
if number % 1_000_000_000_000 == 0
"#{single(number/1_000_000_000_000)} trillion"
else
"#{single(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
end
else
millions(number)
end
end
def billions(number)
if number.between?(100_000_000_000, 999_999_999_999)
if number % 1_000_000_000 == 0
"#{hundreds(number/1_000_000_000)} billion"
else
"#{hundreds(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
end
elsif number.between?(10_000_000_000, 99_999_999_999)
if number % 1_000_000_000 == 0
"#{tens(number/1_000_000_000)} billion"
else
"#{tens(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
end
elsif number.between?(1_000_000_000, 9_999_999_999)
if number % 1_000_000_000 == 0
"#{single(number/1_000_000_000)} billion"
else
"#{single(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
end
else
millions(number)
end
end
def millions(number)
if number.between?(100_000_000, 999_999_999)
if number % 1_000_000 == 0
"#{hundreds(number/1_000_000)} million"
else
"#{hundreds(number/1_000_000)} million #{thousands(number%1_000_000)}"
end
elsif number.between?(10_000_000, 99_999_999)
if number % 1_000_000 == 0
"#{tens(number/1_000_000)} million"
else
"#{tens(number/1_000_000)} million #{thousands(number%1_000_000)}"
end
elsif number.between?(1_000_000, 9_999_999)
if number % 1_000_000 == 0
"#{single(number/1_000_000)} million"
else
"#{single(number/1_000_000)} million #{thousands(number%1_000_000)}"
end
else
thousands(number)
end
end
def thousands(number)
if number.between?(100_000, 999_999)
if number % 1000 == 0
"#{hundreds(number/1000)} thousand"
else
"#{hundreds(number/1000)} thousand #{hundreds(number%1000)}"
end
elsif number.between?(10_000, 99_999)
if number % 1000 == 0
"#{tens(number/1000)} thousand"
else
"#{tens(number/1000)} thousand #{hundreds(number%1000)}"
end
elsif number.between?(1_000, 9_999)
if number % 1000 == 0
"#{single(number/1000)} thousand"
else
"#{single(number/1000)} thousand #{hundreds(number%1000)}"
end
else
hundreds(number)
end
end
def hundreds(number)
if number % 100 == 0
"#{single(number/100)} hundred"
elsif number.between?(101, 999)
"#{single(number/100)} hundred #{tens(number%100)}"
else
tens(number)
end
end
def tens(number)
teens = {
11 => "eleven",
12 => "twelve",
13 => "thirteen",
14 => "fourteen",
15 => "fifteen",
16 => "sixteen",
17 => "seventeen",
18 => "eighteen",
19 => "nineteen"
}
tens = {
1 => "ten",
2 => "twenty",
3 => "thirty",
4 => "forty",
5 => "fifty",
6 => "sixty",
7 => "seventy",
8 => "eighty",
9 => "ninety"
}
if number.between?(11, 19)
teens[number]
elsif number % 10 == 0
tens[number/10]
elsif number.between?(21, 99)
"#{tens[number/10]} #{single(number%10)}"
else
single(number)
end
end
def single(number)
single_digit_hash = {
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
6 => "six",
7 => "seven",
8 => "eight",
9 => "nine"
}
single_digit_hash[number]
end
end
class Integer
include WordsModule
end