しょんぼり技術メモ

まいにちがしょんぼり

億とか京とか

Ruby-listのMLで流れていた、[ruby-list:47175] 金額を漢字フォーマット 億, 千, 万を見て、汎用的に「n桁で区切っていく接頭辞系」を作れないかなと思って試しにやってみた。

#!/usr/bin/ruby -Ku
# -*- coding: utf-8 -*-

Units = [ ""  , "", "", "", "",
          "", "禾予", "", "", "",
          "", "", "", "恒河沙", "阿僧祇",
          "那由他", "不可思議", "無量大数"]
Digit_per_unit = 4

def to_jp_unit(num)
  str = num.to_s
  r_ary = str.split(//).reverse

  result_ary = Array.new
  buf = Array.new
  is_empty = true # zero skip flag

  r_ary.each do |digit|
    buf.unshift(digit)

    is_empty &&= (digit == "0")

    if buf.length >= Digit_per_unit
      if is_empty
        result_ary.unshift("")
      else
        result_ary.unshift("#{buf}#{Units[result_ary.length]}")
      end
      buf.clear
      is_empty = true
    end
  end

  if buf.length > 0
    result_ary.unshift("#{buf}#{Units[result_ary.length]}")
  end

  result_str = ""
  result_ary.each{|part| result_str += part }
  return result_str
end


while(line=gets) do
  num = line.to_i
  puts "#{num} -> #{to_jp_unit(num)}"
end

'Digit_per_unit'で区切る桁数を、Unitsに接頭辞を列挙。Digit_per_unitを3にして、Unitsに"K,M,G,T,P,..."とやれば、SI接頭辞に。

…3(SI接頭辞)と4(命数法)しか思いつかないけど。

実際に万億兆...とやりたい場合は、↑のURLでやってる方法が早いんじゃないかと思います。思いついたままにコーディングしてるので、逆順配列作ったり作業用配列作ったりしてるので遅いはず。


追記

投稿してから気づいたけど、こうすりゃもっとシンプルでした。

def to_jp_unit2(num)
  num_str = num.to_s
  target_digits = num_str.split(//).length
  unit_count    = (target_digits / Digit_per_unit).to_i
  unit_count.downto(0) do |i|
    regexp_str = "([1-9]\\d{0,3})(\\d{#{i*Digit_per_unit}})$"
    replace_to = "\\1#{Units[i]}\\2"
    num_str.sub!(Regexp.new(regexp_str), replace_to)
  end
  num_str.gsub!(/(\D)0+/, '\1')
  return num_str
end