わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

約88文字=256バイト?

ところが図4の例にあるように、この機能は「約88文字以下で入力してください」などと木で鼻をくくったようなエラーを出してくる。じつは、「削除の要請を2回行った」というのは、「約88文字」では説明しきれなかったために2回に分割して送信したという意味だった。

高木浩光@自宅の日記 - 横浜市墓地条例に違反したグーグル社、市の削除要請にも真っ当に応じず, 追記(24日)

「約88文字」とは,何ともおかしな字数です.はてブでも,そこへの突っ込みが目立ちます.

3.削除依頼に詳細を書く欄がありますが、長めに書いたら、「約88文字以内にせよ」とエラー表示され、減らすとまた「約87文字以内にせよ」と言われ、次にまた「約86文字以内にせよ」と言われました。いったいどういうシステムなんですか。「約」が付いていますが、これが免罪符ですか。

ストリートビューについて - 改善、新しい機能の要望 | Google グループ

これを読んで,「UTF-8で日本語88文字は,88×3=264バイトだけど,ASCII文字が入ったりすると,256バイトに収まるってことで,『約88文字』と書いたのかな」と仮説を立てて,実際どんなもんか数えてみることにしました.

#!/usr/bin/env ruby

# char88.rb

$KCODE = 'u'

MAX_CHAR = 88
MAX_BYTE = 256

class String
  # 文字列クラスにメソッドを追加
  def length_byte
    # バイト数(Ruby 1.8/1.9 両対応(のはず))
    unpack('H*').first.length / 2
  end
  def length_char
    # 文字数(Ruby 1.8/1.9 両対応(のはず))
    split(//u).length
  end
  def exceed_byte(len = MAX_BYTE)
    # バイト数超過判定
    length_byte > len
  end
  def exceed_char(len = MAX_CHAR)
    # 文字数超過判定
    length_char > len
  end
end

# 入力ファイル名
xmlfile = ARGV.shift || 'takehikom.xml'
# 試行回数
trial = (ARGV.shift || 10).to_i

# 入力
contents = open(xmlfile).read.split(/\n/).map {|content|
  content.gsub(/\[.*?\]/, '').gsub(/^\*(\d*\*)\s*/, ''). gsub(/&[lg]t;/, '').gsub(/^-+\s*/, '') # 削除すべき文字はまだまだあるけど
}
contents.delete_if {|content| content.empty?}

# バイト数合計
sum_byte = 0
# 文字数合計
sum_char = 0
# バイト数超過の文字列数
count_exceed_byte = 0
# 文字数超過の文字列数(このプログラムでは必ず0)
count_exceed_char = 0

# 1回の試行で,文字数が MAX_CHAR になるよう文字列を取り出し,バイト数を数える.
# これを試行回数分,繰り返す.
trial.times do |i|
  puts "Trial #{i}:"
  pos = rand(contents.length)
  s = ''
  until s.exceed_char
    # 文字数超過になるよう,行単位で追加する
    s += contents[pos]
    pos += 1
    pos = 0 if pos >= contents.length
  end
  while s.exceed_char
    # 文字数超過にならなくなるまで,末尾から1文字ずつ削除する
    s_a = s.split(//u)
    s_a.pop
    s = s_a.join('')
  end

  # 計数,判定
  sum_byte += s.length_byte
  sum_char += s.length_char
  count_exceed_byte += 1 if s.exceed_byte
  count_exceed_char += 1 if s.exceed_char

  # (1回の試行の)出力
  puts "#{s}" if $DEBUG
  puts "#{s.length_byte} bytes#{s.exceed_byte ? '!' : ''}, #{s.length_char} characters#{s.exceed_char ? '!' : ''}"
end

# 結果出力
puts "Result"
puts "trial: #{trial}"
puts "byte: #{sum_byte} / #{trial} = #{sum_byte.to_f / trial}"
puts "char: #{sum_char} / #{trial} = #{sum_char.to_f / trial}"
puts "excess byte: #{count_exceed_byte} / #{trial} = #{count_exceed_byte.to_f / trial}"
puts "excess char: #{count_exceed_char} / #{trial} = #{count_exceed_char.to_f / trial}"

いい文書データがないので,当日記をエクスポートしたXMLファイルを使いました.
プログラムは,もともと,

  • 88文字取り出して,256バイトを超える文字列の件数と割合
  • 256バイト取り出して,88文字未満の文字列の件数と割合

を求めようとしたのですが,後者は不要なことに気づいて実装していません.
Ruby 1.8/1.9両対応の,文字数・バイト数のカウントメソッドを定義しましたが,$KCODEを使っていることから分かるとおり,このプログラム自体はRuby 1.8のもので,実際,1.9では動作確認していません.
それと,辞書を引くと,「超過する」はexceed,その名詞形はexcessだそうです.
ともあれ実行結果は以下の通り.

$ wc takehikom.xml
  23447   38415 2228334 takehikom.xml
$ ruby -d char88.rb takehikom.xml 1000
(略)
Trial 999:
なぜ「cc」なのに「/usr/bin/cc」なのかというと,これは,コマンドサーチパスというものによります.環境変数PATHの情報です.詳細はとりあえず省略.Linux環境では
220 bytes, 88 characters
Result
trial: 1000
byte: 188349 / 1000 = 188.349
char: 88000 / 1000 = 88.0
excess byte: 179 / 1000 = 0.179
excess char: 0 / 1000 = 0.0

自分の日記で,「88文字で256バイトを超える割合」が約18パーセントと出ました.プログラムコード(ASCII文字)がけっこうある日記で,この数値です.言い換えると,文字(日本語)主体の日記から抜き出せば,割合はもっと高くなるでしょう.