Home日記コラム書評HintsLinks自己紹介
 

フィンローダのあっぱれご意見番 第84回「想像できないこと」

← 前のをみる | 「フィンローダのあっぱれご意見番」一覧 | 次のをみる →

初心者向けのドキュメントは大変書くのが難しいものだ。 何が難しいかといえば、初心者というのは一体何が分からないのか、 想像もできないようなことが結構あるのだ。

  

割と対応が簡単なのは、専門用語である。 「専門用語は初心者には分からない」ということは、分かる。 これが分からないようでは初心者向けのドキュメントを書く資格はない。 ところが、俗語や隠語になってくると、途端に怪しくなってしまう。 昔、「フロッピーをコピーしろ」と頼まれた人がXEROXでコピーした、 という有名な伝説があった。 「コピー」という言葉はファイルの複製という意味で用いる限り専門用語なのである。 ところが、「コピー」という単語そのものは、日常生活で普通に使っている。 だから、プラスαの意味が想像できない。 普段の感覚で解釈してしまうのだ。 ニフティサーブ、 FPROGORGで以前「私の落したマシン」という短期会議…というよりも雑談会だが…を開いたことがある。 プログラマーやSEの世界で「マシンを落す」といえば、 OSをシャットダウンすることである。 ただ、この会議は本当に物体を落下させる意味で「落した」という言葉を使っていたのがポイントである。 メインフレームを落したことがあるという人が以前いらっしゃったので、 世の中広いなと思いつつ、こういう会議室を作ったのだ。

 

※ 確かクレーンで吊り上げているときに、 2階程度の高さから落としたという話だったと思う。

§

用語よりもっと難しいのが操作である。 最近、 ニフティサーブインターウェイというサービスが頭痛の種だ。 ちょっと長い名前なので今回はインターウェイと書かせていただく。 最近のいわゆるパソコン通信は、 インターネットからアクセスできるのが当然らしい。 しかも、Netscape Navigatorのようなメジャーなブラウザがあれば、 他に専用ソフトがいらない、というのだ。 普段インターネットに接している人なら、 URLを指定するだけで、 ニフティサーブの従来の「パソコン通信」としてサービスしていた内容をアクセスできるのだ。 便利である。 平成10年11月に実施された平成10年度の「通信利用動向調査」によると、 世帯単位のインターネットの利用率は、 11.0%となっている。 つまり10世帯に1世帯の割合で、 インターネットを使える環境になっているのである。 事業所だと19.2%だから、1/5弱という所か。 特に、自宅以外も含めると20代、30代の約半数がインターネットを利用しているとのことだ。 このような巨大なインフラが現れたら、 パソコン通信というサービスもそのインターフェースを変えるのが当然の成り行きというものである。 おそらく、そのような思惑も込めて始まったであろうサービスが、 インターウェイなのだ。 もちろん、プログラマーズフォーラムの発言も読めます。 気軽に読みに来て欲しい。

と言いたいところだが…。これが難しいのである。 しかし、どう難しいかというのが、最初分からなかった。 というのは、普段何気なく使っている範囲では、 さして難しいものとも思わず、便利なサービス程度の認識しかなかったのだ。

ところが、ある人にこのサービスを紹介することになった。 URLを教えて、出てくるパネルへのIDとパスワードの入力、 このあたりはWebを見なれている人なら簡単だ。 問題はその後である。

プログラマーズフォーラムを見たいのなら、GO FPROGORG。 またはGO FPROG。 これはttyモードの接続時の約束である。 ttyモードって何? いや、従来のパソコン通信のやり方でアクセスすることだと思って欲しい。 いきなり「tty」なんて言われても、 かなりニフティ歴の長い人でもパニックになりそうな気もするが、 とりあえずこだわらない。 話を元に戻せば、要するに、インターウェイの場合、 GOという名前がついたテキストボックスがあるから、 そこにFPROGORGと書いてリターンを押せばいい。

発言を読むのも簡単。 会議室を選べば発言の一覧が出てくる。 発言がリンクになっているので、 ブラウズ感覚で、適当にリンクをクリックしていれば内容を読める。 アクセスが終わったらLOGOUTを押すのを忘れないでくれ。 余談だが、面白いことに、 後ろで見ているとインターウェイで電子メールを出す時に、 接続したままで文章を書いてしまう人が多い。 接続時間の無駄なのだが、 一旦回線を切ってから文章を書くという手順にならない。 面倒さが勝ってしまっているのだ。 月末の請求書でびっくりしなければいいが、 最近はうまく料金体系を選べば死ぬほど高額になることもないのだろう。 メールを出すのを後ろで見ているというのも何だが。

さて、問題はここからだ。なお、念のためはっきりさせておくが、これは実話である。 この人が、もう一度同じ会議室をアクセスしようとした。 ある発言の内容を、もう一度確認するのが目的である。 今度は未読の発言がないので、会議室を選択しても、 最初の画面に発言一覧は現れていない。 発言番号を指定して表示するにはどうすればよいのだろうか? かなり悪戦苦闘していたようだが、 10分ほどかけて、やっとこの発言を表示することに成功したのである。 よかったですね。どこが。なぜ10分もかかってしまうのだ?

なお、この人は、 パソコンおよびそのソフトに関しては、素人ではない。 ワープロや表計算は普通に使えるレベルである。 ニフティサーブも、通常のパソコン通信接続の方法で使っている。 メールで普段連絡できる程度のスキルは持っている。

フォーラムも会議室も発言番号も分かっている。 それさえ指定できれば目的は達成できる。 例えばFPROGORGというフォーラムの6番会議室の発言945番を見たいとしよう。 会議室に入る所まではok、簡単だ。それは認める。この時点で、 画面の下に、図(※)のようなボタンが出ているわけだ。ここで「発言番号」を選んで、 テキストボックスに945と入れる。リターンを押す。 すると「検索の結果、該当発言は 84 件見つかりました。 」という表示が出て、 そのトップが発言945番だ。 なんだ、簡単だ。お騒がせしました。 え、その「84件」って何だって? いや私に訊かれても…。

search

  

というわけで、かなり考えたのだが、 発言945番だけを一発で表示する具体的な方法は、 情けないことだが、私にも発見できなかった。 マニュアルを読めば書いてあるのかもしれない。 マニュアルってどこなのだろう? とりあえず、 本当にどうしようもないかといえば、実は裏技はある。 Netscape Navigatorに直接URL突っ込んでやれば、出る。 もっと具体的に書けば、 https://www.nifty.ne.jp/cgi-bin/go?nifty:fprogorg/mes/10/945 と指定してリターン。 これで一発でその発言を読める。 ちなみにこの発言、 ハノイの塔を解こう、 というスレッドの先頭で、 問題は拡張されていて最適解を求める所まで発展している。

 

※ 今はインターウェイというサービス自体が存在しないので、 もちろんアクセスできない。

§

さて、先月書こうとしてうっかり忘れた話題、 これはFPROGORGの「ROM墓場からの声」という会議室で出た。 この会議室、過去のログは保存しないというしきたりがある。 しかも、毎月4,000以上の発言がある。 NIFTY SERVEの会議室はシステムの制約があって、 1000個以上の発言が行われたら古いものからどんどん自然消滅する。 ということは、この会議室、過去の内容は既にこの世から消えており、 見ることができません。残念。

さて問題は簡単で、1からiまでの整数の和を求めようというのである。 List 1のように書ける。以上。

---- List 1 ----

    int n;
    int total = 0;

    for (n = 1; n <= i; n++) {
        total += n;
    }

---- List 1 end ----

で話が終わるわけがない。 「和を求める」のが目的なら、こんなループを使うのは美しくない。 整数の和を求める公式、n(n+1)/2 程度は、 気の利いた小学生なら知っているのである。 しかし、 流石というか、List 2のように書いた人がいなかった。 オーバーフローするんじゃないか、と話の先を読まれたのである。鋭い。

---- List 2 ----

    total = i * (i + 1) / 2;

---- List 2 end -----

intを32ビット符号付き整数と仮定する。 iの値を46341としてList 2の処理を実行してみると、 totalの値は-1073716337となってしまう。 符号付き32ビットで表現できる最大の数は2147483647。 46341*46342=2147534622だから、 掛け算を実行した時点でこの壁を超えてしまうのである。 (65535×65536/2)の値は2147450880だから、 単純なループを使えば、 結果がlong intの範囲に収まる65535までiの値を扱うことができるのだ。

そこで出てきたのがList 3である。掛け算してから割るのがいかん。 先に割ってしまえばよろしい。しかし単純に2で割ったら、 奇数の時に誤差が発生する。そこで、 iかi+1のどちらかは偶数なのだから、場合分けをする。

---- List 3 ----

    total = ((i & 1) ? i * ((i + 1) / 2) : i / 2 * (i + 1));

---- List 3 end ----

シンプルで言うことがない。ちゃんと65535まで正しい値が出る。 これで話が終わりそうになったので、List 4のようなコードを紹介してみた。

---- List 4 ----

    total = 2 * ((i / 2) * ((i + 1) / 2)) + (i + 1) / 2;

---- List 4 end ----

は? と思った貴方は正しい。 普通はこんなことしない。 しかし書いてみるもので、 さらに出てきたコードがList 5である。

---- List 5 ----

    total = i / 2 * ( i + 1 ) + ( i + 1 ) * ( i & 1 ) / 2;

---- List 5 end ----

List 4が、乗算2回、割り算3回、足し算3回。 List 5は同じく2回、2回、3回と&演算が一回。 つまり、List 3が割り算1回多く、List 5は&が一回多い。 ただ、この割り算は整数演算の2で割る処理、つまりシフト一発で可能だから、 コストとしては&といい勝負だと思う。というわけで、この勝負、引き分けか。

という話ではなくて、 えーと、何でこんな訳のわからないことをするのだ? いや、 電子会議ですから。単なる余興ですがな。 分岐命令を使いたくなかったという説もあるが。 一応65535まで正しく求められるようだし…、ただ、 実はこのコードを書いてから後で考えた。 どうしてこれで正しい値が出るのだとか、どうやって思い付いたのだとか、 さっぱり分からなくなったのである。 とにかく、自分が想像できないようなコードが作れるというのは謎である。

  

(C MAGAZINE 1999年6月号掲載)
内容は雑誌に掲載されたものと異なることがあります。

修正情報:
2006-03-15 裏ページに転載。

(C) Phinloda 1999-2006, All rights reserved.