やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#クイックスタート(数値)

 数値の型や演算子などについて学習する。

成果物

情報源

プロジェクト作成

dotnet new console -n NumbersInCSharp -o .
cd NumbersInCSharp

 備考。以下のように-o .するとソリューションディレクトリが作成されず、ファイルがカレントディレクトリに展開される。

dotnet new console -n NumbersInCSharp -o .

 ウザいので以下のようにしてソリューションディレクトリを作成するようにする。

dotnet new console -o NumbersInCSharp
cd NumbersInCSharp

コード

Program.cs

using System;

namespace NumbersInCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 18;
            int b = 6;
            int c = a + b;
            Console.WriteLine(c);
        }
    }
}

実行

dotnet run

やってみた

 ドキュメントに書いてあるヤツをちょっとだけ自己流にしながら。すると多数のコンパイルエラーに遭遇した。

コンパイルエラー

 とくに最後の面積を求める課題でつまづいた。

CS0220: オーバーフロー

 オーバーフロー時、コンパイルエラーになったようだ。

int what = int.MaxValue + 3;
Program.cs(76,24): error CS0220: この操作はチェック モードでコンパイルしたときにオーバーフローします。 [/tmp/work/NumbersInCSharp/NumbersInCSharp.csproj]

 だが、ドキュメントには負数になると書いてある。

整数がオーバーフローして最大値から最小値に ”折り返され” たため、計算結果が非常に大きな負の値になっています。

 挙動が違う。なぜ? 原因は不明だが、以下のコードに修正するとドキュメントどおりになる。

int max = int.MaxValue;
int what = max + 3;

CS0664: decimalリテラルにはMサフィックスが必要

decimal r = 2.5;
Program.cs(128,25): error CS0664: 型 double のリテラルを暗黙的に型 'decimal' に変換することはできません。'M' サフィックスを使用して、この型のリテラルを作成してください [/tmp/work/NumbersInCSharp/NumbersInCSharp.csproj]

 以下のコードに修正すること。

decimal r = 2.5M;

CS0193: べき乗の演算子**でない

decimal aria = r**2 * Math.PI;
Program.cs(129,30): error CS0193: * または -> 演算子はポインターに対して使用してください。 [/tmp/work/NumbersInCSharp/NumbersInCSharp.csproj]

 べき乗の演算子**でないってことかな? なら^かな?

 以下のコードに修正してみる。

decimal area = r^2 * Math.PI;

 だが、以下のエラーになる。

CS0019: 演算子 '^' を 'decimal' と 'double' 型のオペランドに適用することはできません

decimal area = r^2 * Math.PI;
Program.cs(129,28): error CS0019: 演算子 '^''decimal''double' 型のオペランドに適用することはできません [/tmp/work/NumbersInCSharp/NumbersInCSharp.csproj]

 Math.PIがdouble型なので、これに合わせるしかない。ということかな? 以下のようにコード修正してみる。

double r = 2.5;
double area = r^2 * Math.PI;
Console.WriteLine($"半径{r}cmの円の面積は{area}です。");

 だが、以下のエラーになる。

CS0019: 演算子 '^' を 'double' と 'double' 型のオペランドに適用することはできません

double r = 2.5;
double area = r^2 * Math.PI;
Console.WriteLine($"半径{r}cmの円の面積は{area}です。");
Program.cs(129,27): error CS0019: 演算子 '^''double''double' 型のオペランドに適用することはできません [/tmp/work/NumbersInCSharp/NumbersInCSharp.csproj]

 どうやら型の問題ではないらしい。べき乗の計算をする演算子**でも^でもないってことか?

 ググってみると以下だった。

Math.Pow(r, 2);

 というわけで、以下が答え。

double r = 2.5;
double area = Math.Pow(r, 2) * Math.PI;
Console.WriteLine($"半径{r}cmの円の面積は{area}です。");

 ちなみに、C#における^排他的論理和の意味らしい。ビット演算子

最終的なコード

using System;

namespace NumbersInCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 18;
            int b = 6;
            code0(a, b);
            code1(a, b);
            code2();
            code3();
            code4();
            code5();
            code6();
            code7();
            code8();
            code9();
            code10();
            code11();
            code12();
        }
        static void code0(int a, int b)
        {
            int c = a + b;
            Console.WriteLine(c);
        }
        static void code1(int a, int b)
        {
            Console.WriteLine(a + b);
            Console.WriteLine(a - b);
            Console.WriteLine(a * b);
            Console.WriteLine(a / b);
            Console.WriteLine(a % b);
        }
        static void code2()
        {
            int a = 5;
            int b = 4;
            int c = 2;
            int d = a + b * c;
            Console.WriteLine(d);
            d = (a + b) * c;
            Console.WriteLine(d);
            d = (a + b) - 6 * c + (12 * 4) / 3 + 12;
            Console.WriteLine(d);
        }
        static void code3()
        {
            int e = 7;
            int f = 4;
            int g = 3;
            int h = (e + f) / g;
            Console.WriteLine(h);
        }
        static void code4()
        {
            int a = 7;
            int b = 4;
            int c = 3;
            int d = (a + b) / c;
            int e = (a + b) % c;
            Console.WriteLine($"quotient: {d}");
            Console.WriteLine($"remainder: {e}");
        }
        static void code5()
        {
            int max = int.MaxValue;
            int min = int.MinValue;
            Console.WriteLine($"The range of integers is {min} to {max}");
        }
        static void code6()
        {
            int max = int.MaxValue;
            int what = max + 3;
            Console.WriteLine($"An example of overflow: {what}");
//            int what = int.MaxValue + 3;
//            Console.WriteLine($"An example of overflow: {what}");
        }

        static void code7()
        {
            double a = 5;
            double b = 4;
            double c = 2;
            double d = (a + b) / c;
            Console.WriteLine(d);

            double e = 19;
            double f = 23;
            double g = 8;
            double h = (e + f) / g;
            Console.WriteLine(h);
        }
        static void code8()
        {
            double max = double.MaxValue;
            double min = double.MinValue;
            Console.WriteLine($"The range of double is {min} to {max}");
        }
        static void code9()
        {
            double third = 1.0 / 3.0;
            Console.WriteLine(third);
        }

        static void code10()
        {
            decimal min = decimal.MinValue;
            decimal max = decimal.MaxValue;
            Console.WriteLine($"The range of the decimal type is {min} to {max}");
        }
        static void code11()
        {
            double a = 1.0;
            double b = 3.0;
            Console.WriteLine(a / b);

            decimal c = 1.0M;
            decimal d = 3.0M;
            Console.WriteLine(c / d);
        }

        static void code12()
        {
            double r = 2.5;
            double area = Math.Pow(r, 2) * Math.PI; // べき乗する演算子は`^`でも`**`でもない
            Console.WriteLine($"半径{r}cmの円の面積は{area}です。");
        }
    }
}

最終的な実行結果

$ time dotnet run
24
24
12
108
3
0
13
18
25
3
quotient: 3
remainder: 2
The range of integers is -2147483648 to 2147483647
An example of overflow: -2147483646
4.5
5.25
The range of double is -1.7976931348623157E+308 to 1.7976931348623157E+308
0.3333333333333333
The range of the decimal type is -79228162514264337593543950335 to 79228162514264337593543950335
0.3333333333333333
0.3333333333333333333333333333
半径2.5cmの円の面積は19.634954084936208です。

real    0m56.795s
user    0m20.087s
sys 0m1.710s

勉強になったこと

Console.WriteLine($"{変数名}")

 標準出力のフォーマット形式。いつの間にこんなのができたんだ。

所感

 エラーから正解を推論するには知識と慣れが必要か。だが、それを得るためにはネット検索が必要。

 ビルド&実行がとにかく遅い。もう実行には最低1分かかると思ったほうがいい。とてつもなく遅い。信じられないほど遅い。もうC#触りたくなくなるくらい遅い。とにかく遅い。遅い遅い遅い。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux