module ZhongwenTools::Number
Constants
- NUMBERS_TABLE
TODO: Add huge numbers. en.wikipedia.org/wiki/Chinese_numerals#Large_numbers 垓=亿 (archaic) 秭: 1B or 100B or 1T or 10000T (archaic) 穰 溝 澗 正 載 –> beyond 100,000,000! NOTE: financial numbers i == 0 ? NT.select{ |x| x == i }.last : NT.find{ |x| x = i }
Public Class Methods
number?(obj)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 17 def self.number?(obj) case obj when String regex = /([\d]|#{ZhongwenTools::Regex.zh_numbers}){1,}/ "#{obj}".gsub(regex, '') == '' when Integer, Float true end end
to_zh(obj, type = :zhs, from = nil)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 36 def self.to_zh(obj, type = :zhs, from = nil) case type.to_sym when :zht to_zht(obj, from) else to_zhs(obj, from) end end
Private Class Methods
adjust_integer(number, curr_num)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 156 def self.adjust_integer(number, curr_num) number_multiplier?(curr_num) ? number * curr_num : number + curr_num end
combine_integer(integers, result, curr_num, i)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 149 def self.combine_integer(integers, result, curr_num, i) next_number = integers[i + 1] result += next_number * curr_num if number_multiplier?(next_number) [result, i] end
combine_integers(integers)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 120 def self.combine_integers(integers) return combine_year(integers) if year?(integers) number = 0 length = integers.size skipped = false integers.each_with_index do |curr_num, i| next if skipped == i if (i + 2) <= length number, i = combine_integer(integers, number, curr_num, i) skipped = i + 1 else number = adjust_integer(number, curr_num) end end number end
combine_year(integers)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 145 def self.combine_year(integers) integers.map(&:to_s).join.to_i end
convert(obj, to, from, separator = '')
click to toggle source
# File lib/zhongwen_tools/number.rb, line 47 def self.convert(obj, to, from, separator = '') fail ArgumentError unless [:zhs, :zht, :i, :pyn].include?(to.to_sym) fail ArgumentError unless CONVERTIBLE_OBJECTS.include?(obj.class) number = convert_from from, to, obj if to == :i combine_integers(number) elsif to == :pyn regex = /#{ %w(yi4 wan4 qian1 bai2 shi2).map { |x| 'ling2\-' + x }.join('|')}/ finalize_number(number, '-').gsub(regex, '').gsub(/\-+/, '-').gsub(/\-$/, '') else finalize_number(number) end end
convert_from(from, to, number)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 90 def self.convert_from(from, to, number) if from == :zht convert_from_zh(to, number) elsif from == :zhs convert_from_zh(to, number) elsif from == :i convert_from_integer(to, number) elsif from == :pyn convert_from_pyn(to, number) end end
convert_from_integer(to, int)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 164 def self.convert_from_integer(to, int) # FIXME: this will fail for numbers over 1 billion. result = [] nums = convert_integer_to_reversed_array_of_integers(int) nums.each_with_index do |num, i| wan = wan_level(wan, i) if i == 0 result << convert_integer(num, to) unless num == 0 else if i < 5 result << convert_wan_level(i, to) elsif i == 8 result << convert_wan_level(i, to) else result << "#{ convert_wan_level(i - (i / 4 * 4), to) }#{ convert_wan_level((i / 4 * 4), to) }" end # checks the wan level and ... result << convert_integer(num, to) if wan_ok?(num, wan, i) end end result.reverse! end
convert_from_pyn(to, pyn)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 102 def self.convert_from_pyn(to, pyn) # convert to pyn # split the pyn and then pyns = ZhongwenTools::Romanization::Pinyin.split_pyn(pyn) pyns.map do |p| convert_number(p).fetch(to) { p } end end
convert_from_zh(to, number)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 112 def self.convert_from_zh(to, number) converted_number = number.chars.map do |zh| convert_number(zh).fetch(to) { zh } end converted_number end
convert_integer(int, to)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 209 def self.convert_integer(int, to) NUMBERS_TABLE.find { |x| x[:i] == int }.fetch(to) { 0 } end
convert_integer_to_reversed_array_of_integers(int)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 190 def self.convert_integer_to_reversed_array_of_integers(int) int.to_s.chars.to_a.reverse.map(&:to_i) end
convert_number(number)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 213 def self.convert_number(number) NUMBERS_TABLE.find { |x| x[:zhs] == number || x[:zht] == number || x[:pyn] == number } end
convert_wan_level(i, to)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 205 def self.convert_wan_level(i, to) convert_integer((10**(i)), to) || convert_integer((10**(i) / 10_000), to) || convert_integer((10**(i) / 10_000**2), to) end
finalize_number(number, separator = '')
click to toggle source
# File lib/zhongwen_tools/number.rb, line 217 def self.finalize_number(number, separator = '') # FIXME: is finalize_number the best name you can think of? # NOTE: Figuring out usage of "liang" vs. "er" is pretty # difficult, so always use "er" instead. number.join(separator).gsub(/零#{ Regex.zh_number_multiple }*/u, '') end
number_multiplier?(number)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 160 def self.number_multiplier?(number) [10, 100, 1_000, 10_000, 100_000_000].include? number end
number_type(obj)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 63 def self.number_type(obj) klass = obj.class if NUMBER_CLASSES.include?(klass) :i else if ZhongwenTools::Zhongwen.zh?(obj) if zht?(obj) :zht else :zhs end else # assume it is pyn # FIXME: might need to convert to pyn :pyn end end end
wan_level(wan, i)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 198 def self.wan_level(wan, i) wan ||= 0 wan += 1 if (i + 1) % 5 == 0 wan end
wan_ok?(num, wan, i)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 194 def self.wan_ok?(num, wan, i) (num == 1 && (10**(i) / 10_000**wan) != 10) || num != 1 end
year?(integers)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 141 def self.year?(integers) integers.select { |i| i < 10 }.size == integers.size end
zhs?(str)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 86 def self.zhs?(str) !zht?(str) end
zht?(str)
click to toggle source
# File lib/zhongwen_tools/number.rb, line 82 def self.zht?(str) str[/#{ZhongwenTools::Regex.zht_numbers }*/] == str end