コンピュータアルゴリズムの授業の宿題のドラフト '(draft (homework (class (computer-algorithm))))

問題

  • ちょっと変な課題を出してみたいと思う。教科書59頁のリスト3-10(Array4.java)に対して,プログラミングを始めたばかりの高校生が以下のような質問をしてきた。君なら何と答える?自分の言葉で説明するように!
    • 「Array4.java において配列 a, b を定義して,a は {1, 2, 3} で初期化しているから,各々の要素に対する実体(メモリ)が確保されて,そこに 1, 2, 3 が代入されています。その後 b=a; と a を b に「代入」しています。この場合,b 用に実体(メモリ)が確保されて,b の実体に対して,b[0]=a[0], b[1]=a[1] というように各々の値がコピーされるのでは「なく」,b=a; というのは,b を a の「別名,あだ名」として初期化している,,,,と説明されました。でも,a, b が普通の int 型なら,b=a; は,a の内容を b にコピーする,という意味なんだから,a, b が配列の時だって,b=a; というのは,a の内容が b にコピーされる,と解釈するのが自然だと思います。配列の時だって,a の内容が b にコピーされる,というように考えちゃいけないんですか?あだ名とか,別名とか,何か変!そもそも,b=a; という見た目が同一の表現にどうして複数の解釈を要求するのか,それがよく分かりません!変なの!」 <<

解答草案

問題文に対抗して、会話するように解答する。

「そうだね、一見変かもしれない。僕もプログラミングを始めたころは、値のコピーとあだ名の違いを混同して、よく困っていた。
なぜ同じ = を使うのに、"代入"と"あだ名"があるのか考えてみよう。その前に、説明に使う言葉についてちょっと話そう。配列やなんかの"あだ名"である変数のことを、専門用語で"参照型変数"と言うんだ。それに対応して、integerみたいな値を扱う変数を基本データ型変数、または基本型変数という。これからは参照型変数、基本型変数という言葉を使うことにするよ。
なぜ基本型変数と、参照型変数というものがあるのか。一見わかりにくい気もするけど、Javaを作った人たちだって馬鹿じゃないはずだ。きっと色々考えた結果、Javaにはこの2種類の変数が必要だという結論に達したから、Javaは今のような姿で存在するはずだよね。
(work in progress)」

  • 文脈重要(いい例がなかなか思い浮かばない
  • 配列変数が、ポインタ的振舞いをする場合のメリット
    • foo
    • bar
  • 配列変数が、ポインタ的振舞いをしない場合のデメリット
    • 新たにメモリ領域を確保して、値を複製するコストが大きい
    • メモリ領域が無駄

他にも本質的に重要な点があると思うのだけど、思いつかない。

ちなみに、クラスなどの変数が値ではなく参照の場合、ある状態から複数の発展方法をシミュレートするときに結構面倒。ある状態を1つのインスタンスとして、そのインスタンスを複製して状態を発展させていくときに、参照と値の違いをしらないと、ちゃんとシミュレートできない。まあ、大抵の場合、状態はパラメタをくまなく集めてこれば決定されるから、パラメタをくまなく集めてコピーすればそれでインスタンスの複製ができちゃうけど。

参考になりそうなソース

問題

教科書 76頁において,加算演算子('+')が多種多様な機能を持つことを学んだ。「文字列 '+' 数値」なんてのは,ピントこなかった人もいると思う。授業でこれまで扱った型(基本型と文字列)を使って,色んなものを「足してみて」Javaが定義する '+' の多様性を確認せよ。数値と言っても,float やら double やらあるでしょう。また,'+' 記号にここまで多様な機能を持たせる,というのは,作ったプログラムが「思いも寄らぬ動作」をする('+' 記号が,思った以上のことをしてしまうが為に,こちらの意図通りに動作してくれない)可能性がでてくると思われるが,この点についてどの思うか?素直な感想を述べよ(君がプログラミング言語を設計する場合,どういう戦略を立てるのか,というのを考えてみよ)。

解答草案

  • 文字列 + 数値 #=> 文字列なんて気持ちわりーんだよばーか
    • Javaって厳密そうな顔してるくせに
    • 俺は明示的に文字列に変換する派
      • でもたまにサボる
  • 文字列 + 数値.toString() とかですよね
  • 例えば、数値の場合
    • 型に優先度をつける
    • double > float > long > int > short とか
    • 異なる数値の型同士で演算する場合は、優先度が高い型に自動的にキャストする
    • 多分多くの言語がそんな感じ?
    • 小数と有理数は、明示的にキャストしないとエラーくらいでもいいと思っている
      • でも必要がないなら明示的にキャストすることはない俺
  • 個人的には、rational型(有理数)があるとうれしいかも。

結論としては、RubySchemeがあれば世界は今日も平和ってことですよ。

問題

int型のキャスト「(int)」を用いて double 型の変数 x を四捨五入して int 型にするにはどのようにすればよいか。x が負の数の時のことも考慮して回答せよ。

解答草案

double foo = [value];
int ret;

ret = (int)foo;
if ((foo - ret) <= 0.5){
  ret++;
}

とかでいいんだろうか。未確認。