課題の進め方
基本的には適当なプロジェクト/ソリューションを作って課題を進めた上で,Program.cs
のみ(特に他に指示がなければ)を提出する.
他の人(受講者・非受講者両方)に解答内容(一部でも)を見せない,そして他の人の解答内容(一部でも)を見ないようお願いします.特に,公開の場所に解答を置かないようお願いします.githubやbitbucket等は使える人は使えばよいと思いますが,privateレポジトリにするようにお願いします.
プロジェクト/ソリューションの作成
Note
再掲:プロジェクトは一つの実行形式やライブラリを作成するためのコード等を全てまとめたものであり,ソリューションは関連するプロジェクトをまとめたもの(参考:What are solutions and projects in Visual Studio).
適当な名前(たとえば課題3の解答なのでQ3
にするなど)のフォルダを適当な場所に作成し,
VSCodeで作成したフォルダを開く.そして,VSCode内のターミナルで以下を実行する.
dotnet new console -o .
課題の実施
Program.cs
を問題文の指示の通りに編集する(提出・採点手続きの簡略化のため提出する.csファイルは一つのみ).作成した.csファイルには先頭部分に学籍番号と名前をコメントとして含めること.なので,たとえば学籍番号Z0TB9999の東北 大学さんの提出ファイルは
// Z0TB9999
// 東北 大学
という行から始まる.
提出
できあがった Program.cs
をClassroom内の当該回の「課題」より提出する.最初のステップで作成したフォルダにあるはず.また問題文に指示がある場合はそのファイル(例:課題4のitems.txt)も提出する.提出前には以下を確認しよう.
- 提出プログラムコードのファイル名は
Program.cs
になっているか - 提出するファイルに学籍番号と名前がコメントとして含まれているか
- 文献やWebサイトを参考にした場合は文献の情報やURLおよびアクセス日に加えて元文献のどの部分を参考にしたのかがコードの当該箇所付近のコメントとして記述されているか
- 友人と相談した・された場合はその友人の名前および大雑把な相談の内容がコメントとして書かれているか
- ただし,友人の解答を見ない,そして友人に解答を見せないようお願いします
- TA・教員と相談した場合は,その旨と大雑把な相談の内容がコメントとして書かれているか
基本課題
「電卓」を表す以下のCalc
クラスについて考える.
using System;
// 以下のクラスは変更してはならない.
class Calc
{
// 現在の値
protected double val;
public Calc()
{
= 0;
val }
public virtual void Set(double d)
{
= d;
val }
public virtual void Add(double d)
{
+= d;
val }
public virtual void Sub(double d)
{
-= d;
val }
public virtual void Mul(double d)
{
*= d;
val }
public virtual void Div(double d)
{
/= d;
val }
public void Report()
{
.WriteLine("Value: " + val);
Console}
}
このCalc
クラスを継承し,以下のメソッドを備えた関数電卓クラスFunCalc
を作成せよ.ただし,Calc
クラスを変更してはならない.
メソッド | 説明 |
---|---|
public void Pow(double d) |
「現在の値」をd 乗にする. |
public void SetLogBase(double d) |
「logの底」をd に設定する. |
public void Log() |
「現在の値」をそのlog(底は「logの底」)に設定する. |
public void SetRadianMode() |
「角度の単位」をラジアンに設定する. |
public void SetDegreeMode() |
「角度の単位」を度に設定する. |
public void Sin() |
「現在の値」を角度(度かラジアンかは「角度の単位」による)として,そのsinに「現在の値」を設定する. |
public void Cos() |
「現在の値」を角度(度かラジアンかは「角度の単位」による)として,そのcosに「現在の値」を設定する. |
これらのメソッドを実装するためにFunCalc
は適当なフィールド(ひとつとは限らない)を持つ必要がある.そうしたフィールドはpublicにはしないようにすること.また,度をラジアンに直す等の共通の処理はprivateなメソッドにまとめるとよい.
提出するプログラムは以下のクラスProgram
を持つこと.
class Program
{
static void RepeatDiv(Calc c, double d, int n) {
for (int i = 0; i < n; i++) {
.Div(d);
c}
}
static void Main(string[] args)
{
= new FunCalc();
FunCalc fc
// 16 / 2 / 2 / 2 / 2
.Set(16);
fcRepeatDiv(fc,2,4); // fcはCalcのインスタンスとしても使用可
.Report();
fc
// sin(30°)の計算
.SetDegreeMode();
fc.Set(30);
fc.Sin();
fc.Report();
fc
// sin(30°)の計算(少し別の方法)
.Set(30);
fc.SetDegreeMode();
fc.Sin();
fc.Report();
fc
// cos(π)の計算
.SetRadianMode();
fc.Set(Math.PI);
fc.Cos();
fc.Report();
fc
// SetDegreeMode()およびSetRadianMode()は「現在の値」には影響しない.
.Set(10);
fc.SetDegreeMode();
fc.SetDegreeMode();
fc.Report();
fc.SetRadianMode();
fc.SetRadianMode();
fc.Report();
fc
// 2^10
.Set(2);
fc.Pow(10);
fc.Report();
fc
// log₂(2^10)
.SetLogBase(2);
fc.Log();
fc.Report();
fc
// log₁₀(log₂(2^10))
.SetLogBase(10);
fc.Log();
fc.Report();
fc}
}
期待される出力の例
Value: 1
Value: 0.49999999999999994
Value: 0.49999999999999994
Value: -1
Value: 10
Value: 10
Value: 1024
Value: 10
Value: 1
Note
sinやcos,logや累乗を計算するのにはMath
クラスのstaticメソッドSin(double)
,Cos(double)
,Log(double,double)
,Pow(double,double)
が利用できる.
πについてもMath.PI
が利用可能である.詳細は,.NET API リファレンスの関連ページを参照のこと.特に,Log
やPow
がどっちの引数が何を表しているかをちゃんと確認するとよい.
また言うまでもないかもだが,180° = πラジアン である.
発展課題
Important
本課題を完了できたのならば本課題の解答のみを提出すればよく,基本課題の解答は提出する必要はない.
基本課題で作成した FunCalc
の一部の関数を変更し,不正な値が与えらえたときにエラーとして扱い,計算等はせずに Error!
と表示するようにせよ. ただし,Calc
クラスを変更してはならない.
具体的には以下のメソッドの動作を変更すれば十分である.
メソッド | 変更点 |
---|---|
SetLogBase(double d) |
d が0以下か,1であればエラーとする |
Log() |
メソッド呼び出し時点においてval が0以下であればエラーとする |
Div(double d) |
d が0であればエラーとする |
また,Program.Main
にたとえば以下のように動作確認用の記述を追加してよい(既存の処理を削除してはならない).
class Program
{
// … 基本課題と同じ部分については省略 …
static void Main(string[] args)
{
= new FunCalc();
FunCalc fc
// … 基本課題と同じ部分については省略 …
// エラー処理の動作確認用
.Div(0); // Error!
fc.Report(); // 直前のfc.Report()と同じ値が表示される
fc.Set(0);
fc.Log(); // Error!
fc.Report(); // Value: 0
fc.SetLogBase(-1); // Error!
fc.SetLogBase(1); // Error!
fc}
}
ヒント: 一部の実装にはオーバライドを使う?