fc2ブログ

ネタつつき163 - 掛算と割り算の本質は同じ

 以前私は、抽象的に見れば、足し算と引き算は本質的に同じだと書きました。この話題から当然湧く疑問は、掛け算と割り算の共通性です。という事で、昨晩少し考えてみました。
 掛算と割り算の分析をしてみて感じたのは、この両演算は一次関数と似ているという事です。例えば、2 * 4 = 8、7 / 3 = 2 ..余り2です。これを一次関数に書き直すとy = 2x + b です。掛け算の余りを0と仮定すると、それぞれが 2x + 0と2x + 1 です。これを微分すれば両方とも2です。この事から、掛け算と割り算は超離散しているだけのグラフを描くように見えます。
 その考えを元に、今度は掛け算と割り算について、共通ルーチンを使う形で実装してみました。今度のサンプルは、ちょっと複雑になったので、オブジェクト指向の洗礼(プログラマージョーク)をしています。構造的にちょっと見やすくなっていると思います。

//Main
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;

static class Program
{
    static void Main()
    {
        CycleTableTest( );
        Console.WriteLine( );
        NumberTest( );
    }

    static void NumberTest()
    {
        char[ ] table = new char[ ] {
                '0', '1', '2', 
                '3', '4', '5', 
                '6', '7', '8',
                '9'
            };
        NumberUnit obj = new NumberUnit(
            new CycleTable( table ) );

        //インクリメントとデクリメントの共通表示処理
        Action<string, Func<char, string>> Print =
            ( string msg, Func<char, string> f ) => {
                Console.WriteLine( msg );
                foreach ( char value in table ) {
                    Console.WriteLine( "{0}を代入した結果は? : {1}",
                        value,
                        f( value ) );
                };
                Console.WriteLine( );
            };

        //インクリメント
        Print( "インクリメントします・・・",
            ( char x ) => obj.Increment( x ).ToString( ) );

        //デクリメント
        Print( "デクリメントします・・・",
            ( char x ) => obj.Decrement( x ).ToString( ) );

        //加算と減算の共通表示処理
        Action<char, char, char, Func<char, char, string> > show =
            ( char x, char ope, char y, Func<char, char, string> f ) => {
                Console.WriteLine( "{0} {1} {2} = {3} ",
                    x, ope, y, f( x, y ) );
            };
        Action<string, char, Func<char, char, string>> Print1 =
            ( string msg, char ope, Func<char, char, string> f ) => {
                Console.WriteLine( msg );
                show( '0', ope, '0', f );
                show( '2', ope, '3', f );
                show( '3', ope, '6', f );
                show( '4', ope, '2', f );
                show( '7', ope, '3', f );
                show( '9', ope, '9', f );
                Console.WriteLine( );
            };

        //足し算
        Print1(
            "加算演算子を試します・・・",
            '+',
            ( char v, char v1 ) => ( obj.Add( v, v1 ) ).ToString( ) );

        //引き算
        Print1( "減算演算子を試します・・・",
            '-',
            ( char v, char v1 ) => ( obj.Sub( v, v1 ) ).ToString( ) );

        //掛け算
        Print1(
            "乗算演算子を試します・・・",
            '×',
            ( char v, char v1 ) => ( obj.Mul( v, v1 ) ).ToString( ) );

        //掛け算
        Print1(
            "除算演算子を試します・・・",
            '÷',
            ( char v, char v1 ) => ( obj.Div( v, v1 ) ).ToString( ) );

        //比較
        Console.WriteLine( "値の比較を試します・・・" );
        Func<int, string> GetString = ( int v ) => {
                switch ( v ) {
                    case -1:
                        return "右の値の方が大きい";
                    case 0:
                        return "両方の値は同じ";
                    case 1:
                        return "左の値の方が大きい";
                }
                throw new ArgumentException( );
            };
        Console.WriteLine( "{0}と{1}どちらが大きい?{2}",
            '5' , '4',GetString( obj.CompareTo( '5', '4' ) ) );
        Console.WriteLine( "{0}と{1}どちらが大きい?{2}",
            '5', '5', GetString( obj.CompareTo( '5', '5' ) ) );
        Console.WriteLine( "{0}と{1}どちらが大きい?{2}",
            '5', '6', GetString( obj.CompareTo( '5', '6' )  ) );

        //終了
        Console.ReadLine( );
    }

    static void CycleTableTest()
    {
        char[ ] table = new char[ ] {
                '0', '1', '2', 
                '3', '4', '5', 
                '6', '7', '8',
                '9'
            };
        CycleTable obj = new CycleTable( table );

        Console.WriteLine( "次の値を表示します・・・" );
        foreach ( char value in table ) {
            Console.WriteLine( "{0}を代入した結果は? : {1}, " +
                "1週回った?:{2}",
                value,
                obj.Next( value ),
                obj.IsLast );
        };
        Console.WriteLine( );

    }
}

//NumberUnit
using System;
using System.Text;
using System.Collections.Generic;

enum Sign
{
    Plus,
    Minus
}


//1桁の数字を抽象化したもの
class NumberUnit
{
    //記号表
    CycleTable _table;
    CycleTable _rTable;

    //記号表が必要となる
    public NumberUnit(
        CycleTable table )
    {
        this._table = table;
        this._rTable = table.Reverse( );
    }

    //インクリメント演算
    public Value Increment(
        char value )
    {
        char lowValue = this._table.Next( value );
        char highValue = this._table.First;
        if ( this._table.IsLast ) {
            highValue = this._table.Next( highValue );
            this._table.Reset( );
        }
        Sign sign = Sign.Plus;
        return new Value(
            sign,
            highValue,
            lowValue,
            this._table.First );
    }

    //デクリメント演算
    public Value Decrement(
       char value )
    {
        if ( value == this._table.First ) {
          return new Value(
            Sign.Minus,
            this._table.First,
            this._table.Begin,
            this._table.First );
        }
        char lowValue = this._rTable.Next( value );
        char highValue = this._table.First;
        Sign sign = Sign.Plus;
        if ( this._rTable.IsLast ) {
            sign = Sign.Minus;
            this._rTable.Reset( );
        }
        return new Value(
            sign,
            highValue,
            lowValue,
            this._table.First );
    }

    //2つの引数を受け取る演算
    //記号表と照らし合しながら値を導出
    private Tuple<bool, char> Operator(
        CycleTable usetTable,
        char value,
        char value1 )
    {
        CycleTable workTable = this._table.Copy( );
        char temp = workTable.First;
        char result = value;
        while ( value1 != temp ) {
            result = usetTable.Next( result );
            temp = workTable.Next( temp );
        }
        bool flag = usetTable.IsLast;
        usetTable.Reset( );
        return new Tuple<bool, char>(
            flag, result );
    }

    //加算演算
    public Value Add(
        char value,
        char value1 )
    {
        Tuple<bool, char> temp = this.Operator(
            this._table,
            value,
            value1 );
        Sign sign = Sign.Plus;
        char lowValue = temp.Item2;
        char highValue;
        if ( temp.Item1 ) {
            highValue = this._table.Begin;
        } else {
            highValue = this._table.First;
        }
        return new Value(
            sign, 
            highValue, 
            lowValue, 
            this._table.First);
    }

    //減算演算
    public Value Sub(
        char value,
        char value1 )
    {
        Tuple<bool, char> temp;
        char v = value;
        char v1 = value1;
        Sign sign;
        if ( this.CompareTo( value, value1 ) >= 0 ) {
            temp = this.Operator(
                this._rTable,
                value,
                value1 );
            sign = Sign.Plus;
        } else {
            temp = this.Operator(
                this._rTable,
                value1,
                value );
            sign = Sign.Minus;
        }
        char highValue = this._table.First;
        char lowValue = temp.Item2;
        return new Value(
            sign,
            highValue,
            lowValue,
            this._table.First );
    }

    //比較
    public int CompareTo( char v, char v1 )
    {
        //エラーチェック
        if ( !this._table.Contains( v ) ) {
            throw new ArgumentException(
                v + "は無効な記号です。" );
        }
        if ( !this._table.Contains( v1 ) ) {
            throw new ArgumentException(
                v1 + "は無効な記号です。" );
        }

        //どちらが先に到達するまでチェック
        char temp = this._table.First;
        bool vHit = false;
        bool vHit1 = false;
        char tmp1 = this._table.First;
        while ( true ) {
            if ( temp == v ) vHit = true;
            if ( tmp1 == v1 ) vHit1 = true;
            if ( vHit || vHit1 ) break;
            temp = this._table.Next( temp );
            tmp1 = this._table.Next( tmp1 );
        }

        //どちらが先に到達したのか
        if ( vHit ) {
            if ( vHit1 == false ) return -1;
            return 0;
        } else {
            if ( vHit1 ) return 1;
            return 0;
        }
    }

    //3つの引数を受け取る演算
    private Value Operator(
        char addValue,
        char subValue,
        char remainder )
    {
        if ( addValue == this._table.First ||
            subValue == this._table.First ) {
            return new Value( this._table.First );
        }
        Value temp = new Value(
           Sign.Plus,
           this._table.First,
           this._table.First,
           this._table.First,
           remainder );
        char highValue = this._table.First;
        char lowValue = this._table.First;
        while ( remainder >= subValue ) {
            Value v = this.Add( lowValue, addValue );
            lowValue = v.LowValue;
            if ( v.IsHighValue ) 
                highValue = this.Increment( highValue ).LowValue;
            remainder = this.Sub( remainder, subValue ).LowValue;
            temp = new Value(
                Sign.Plus,
                highValue,
                v.LowValue,
                this._table.First,
                remainder );
        }
        return temp;
    }

    //乗算演算
    public Value Mul(
        char value,
        char value1 )
    {
        return this.Operator(
            value,
            this._table.Begin,
            value1 );
    }

    //除算演算
    public Value Div(
        char value,
        char value1 )
    {
        return this.Operator(
            this._table.Begin,
            value1,
            value );
    }
}

using System;
using System.Collections.Generic;
using System.Linq;

//記号表を管理するオブジェクト
class CycleTable
{
    //記号列
    IEnumerable<char> table;

    //開始記号
    char _first;
    public char First
    {
        get { return this._first; }
    }

    //終了記号
    char _last;
    public char Last
    {
        get { return _last; }
    }

    //開始記号の次
    char _begin;
    public char Begin
    {
        get { return _begin; }
    }

    //テーブルの終了を過ぎたか?
    bool _lastFlag;
    public bool IsLast
    {
        get { return this._lastFlag; }
    }
    
    //記号列を指定してインスタンスを生成
    public CycleTable( IEnumerable<char> table )
    {
        this.table = table;
        this._first = this.table.First( );
        this._last = this.table.Last( );
        this._begin = this.Next( this._first );
    }

    //次の記号を返す
    public char Next( char value )
    {
        //エラーチェック
        if ( !table.Contains( value ) ) {
            throw new ArgumentException(
                value + "は無効な記号です。" );
        }

        //初期値設定
        IEnumerator<char> ie = this.table.GetEnumerator( );
        ie.MoveNext( );

        //検索
        while ( value != ie.Current ) ie.MoveNext( );
        if ( ie.Current == _last ) {
            //終了まで達したら開始記号を返す
            this._lastFlag = true;
            return _first;
        } else {
            ie.MoveNext( );
            return ie.Current;
        }
    }

    //オブジェクトの状態をリセットする
    public void Reset()
    {
        this._lastFlag = false;
    }

    //記号表を逆にしたオブジェクトを返す
    public CycleTable Reverse()
    {
        return new CycleTable( this.table.Reverse( ) );
    }

    //同じ記号表を持つオブジェクトを返す
    public CycleTable Copy()
    {
        return new CycleTable( this.table );
    }

    //記号表に存在するかチェック
    public bool Contains( char target )
    {
        return this.table.Contains( target );
    }
}

共通性を強くアピールするために、0除算のエラーチェックはしていませんが、両演算はほぼ同じだと分かると思います。違いはエラーチェックと、特殊な状況です。これは、加算と減算にも言えます。減算でマイナス値を算出するときに工夫するのと同じです。
 情報技術力?を鍛えると、情報技術を学ぶ前に見えなかったものが見えてきます。乗算と除算と言えば、表と裏のように両極端に感じる人が多いと思います。しかし、それらの物事も視点を変え抽象化してみれば、思わぬ共通性が見えてきます。これこそが、情報技術の魅力なのかもしれませんね。
スポンサーサイト



テーマ : 文明・文化&思想
ジャンル : 学問・文化・芸術

ネタつつき162 - 直書き(変化を考えない)は悪

 今回はプログラミングの常識と、その考えを日常の出来事に適応することについて書きます。前記事のサンプルプログラムには、プログラミング上許されない間違えがあります。それは・・・

//加算演算
public string Add(
    char value,
    char value1 )
{
    Tuple<bool, char> result = this.Operator(
        value,
        value1,
        ( char v ) => this.increment( v ) );
    if ( result.Item1 ) return "1" + result.Item2;
    else return result.Item2.ToString( );
}

 このプログラムに文字列リテラルを直書きしています。このサンプルがアラビア数字だったからいいものの、アラビア数字以外の記号でプラス演算をする場合に対応できません。この部分は通常導出して対応します。

//加算演算
public string Add(
    char value,
    char value1 )
{
    Tuple<bool, char> result = this.Operator(
        value,
        value1,
        ( char v ) => this.increment( v ) );
    if ( result.Item1 ) 
        return 
            this.increment( this.first ).Item2.ToString() 
            + result.Item2;
    else 
        return result.Item2.ToString( );
}

 プログラミングでは、将来起こるであろう変化や汎用性も考慮して行います。この考え方は、プログラマーにとって常識なのですが、世間一般ではそうでないようです。例えば、法律の条文は全て直書きです。これは非常に問題です。
 何故ならば、物価が変わっても罰則金は同じだからです。また、犯罪手段が増えても、なぜか手段を直書きしているので、「このストーカーはメールを使っている。条文に書かれていないから立件できない」などといった愚かなことが起こっています。こういったことを許すと、犯罪者にとって非常に有利に働きます。
 念のためにもう一例挙げると、日本にブラック会社が多いのも、こうした変化に対処することが立法時に考えられていないのが原因だと思います。何故ならば、罰則がゆるく、犯罪をした方がもうかるからです。これでは、ローリスクハイリターンであり、犯罪を誘発しているといっても過言ではありません。もともと犯罪をする人たちは、倫理観が欠如している人ですから、法律の不備により儲かるならば、「ローリスクハイリターンならば当然する」と考えるでしょう。
 この2つの例からもわかるように、変化を考慮せず、固定化した定義を設けるのは悪以外の何物でもありません。プログラミングではエラーが起こり、社会では犯罪者が跋扈するのです。
 勘違いがないように念押しに一つ書くと、日本人は論理で考えず、空気で判断している傾向があるので、こうした悪い人が有利に働く場面が多いです。貴方の職場でも、理不尽がまかり通っているのではないでしょうか?病院、学校、売り場、社内・・・日本の全てに、理不尽が蔓延しています。ニュースの一つを聞いても、理論的に考えられておらず、何度も同じ事件が起こっているのがわかるでしょう。何故か最近は、ニュースキャスターが異例を連呼していますが、ほぼすべてが同様の事件が過去に起こっています。過去の教訓が何も生かされていない証拠だと言えます。
 纏めます。直書き、すなわち、変化を考慮しない事は悪を誘発します。これはプログラミングに限った話ではありません。プログラマー以外の人も常に変化を前提に考えるべきだ私は思います。そうすれば、日本に蔓延している理不尽が消え、より住みよい社会になるでしょう。

テーマ : 文明・文化&思想
ジャンル : 学問・文化・芸術

ネタつつき161 - 技術者のお遊びで足し算の原理を実装した件

 昨日は気晴らしに、数オブジェクトを実装してみました、もちろん数値型は使用せずに実装します。何故ならば、数オブジェクトの実装で、数値型を使用するのはズルをしているのと同じだからです。数値型は既に数を表わすものとして実装されているものですから、それを使用するのはおかしいです。
 プログラミングで一切の数を使わないのはちょっとした刺激でした。さくっと書いたものですから、洗礼されていません。ちょっとしたお遊びで書いたものですからご容赦ください。

using System;
using System.Collections.Generic;
using System.Linq;

class Sample
{
    static void Main()
    {
        char[ ] table = new char[ ] {
                '0', '1', '2', 
                '3', '4', '5', 
                '6', '7', '8',
                '9'
            };
        Number obj = new Number( table );

        //インクリメントとデクリメントの共通表示処理
        Action< string, Func<char, Tuple< bool, char >> > Print =
            ( string msg, Func<char, Tuple<bool, char>> f ) => {
                Console.WriteLine( msg );
                foreach ( char value in table ) {
                    Console.WriteLine( "{0}を代入した結果は? : {1}",
                        value,
                        f( value ) );
                };
                Console.WriteLine( );
            };

        //インクリメント
        Print( "インクリメントします・・・",
            ( char x ) => obj.increment( x ) );

        //デクリメント
        Print( "デクリメントします・・・",
            ( char x ) => obj.Decrement( x ) );

        //加算と減算の共通表示処理
        Action<string, char, Func<char, char, string>> Print1 = 
            ( string msg, char ope, Func<char, char, string> f ) => 
            {
                Console.WriteLine( msg );
                Console.WriteLine( "{0} {1} {2} = {3} ",
                    '0', ope, '0', f( '0', '0' ) );
                Console.WriteLine( "{0} {1} {2} = {3} ",
                    '8', ope, '3', f( '8', '3' ) );
                Console.WriteLine( "{0} {1} {2} = {3} ",
                    '0', ope, '5', f( '0', '5' ) );
                Console.WriteLine( );
            };

        //足し算
        Print1(
            "加算演算子を試します・・・",
            '+',
            ( char v, char v1 ) => ( obj.Add( v, v1 ) ) );

        //引き算
        Print1( "減算演算子を試します・・・",
            '-',
            ( char v, char v1 ) => ( obj.Sub( v, v1 ) ) );

        //終了
        Console.ReadLine( );
    }
}

//数字を抽象化したもの
class Number
{
    IEnumerable<char> table;
    char first;
    char last;

    //記号表が必要となる
    public Number(
        IEnumerable<char> table )
    {
        this.table = table;
        this.first = this.table.First( );
        this.last = this.table.Last( );
    }

    //指定した値の次の値を返す
    private Tuple<bool, char> Next(
        IEnumerable<char> searchTable,
        char limit,
        char start,
        char target )
    {
        //エラーチェック
        if ( !searchTable.Contains( target ) ) {
            throw new ArgumentException(
                target + "は無効な記号です。" );
        }

        //初期値設定
        IEnumerator<char> ie = searchTable.GetEnumerator( );
        ie.MoveNext( );
        bool flag = false;

        //検索
        char hit;
        while ( target != ie.Current ) {
            ie.MoveNext( );
        }
        if ( ie.Current == limit ) {
            hit = start;
            flag = true;
        } else {
            ie.MoveNext( );
            hit = ie.Current;
        }
        return new Tuple<bool, char>( flag, hit );
    }

    //インクリメント演算
    public Tuple<bool, char> increment(
        char value )
    {
        return this.Next(
            this.table,
            this.last,
            this.first,
            value );
    }

    //デクリメント演算
    public Tuple<bool, char> Decrement(
       char value )
    {
        IEnumerable<char> rTable = this.table.Reverse( );
        return this.Next(
            rTable,
            this.first,
            this.last,
            value );
    }

    //2つの引数を受け取る演算
    //記号表と照らし合しながら値を導出
    private Tuple<bool, char> Operator(
        char value,
        char value1,
        Func<char, Tuple<bool, char>> f )
    {
        IEnumerator<char> workTable =
            new List<char>( this.table ).GetEnumerator( );
        workTable.MoveNext( );
        char tmp = value;
        bool flag = false;
        while ( value1 != workTable.Current ) {
            var result = f( tmp );
            if ( result.Item1 ) {
                flag = true;
            }
            tmp = result.Item2;
            workTable.MoveNext( );
        }
        return new Tuple<bool, char>( flag, tmp );
    }

    //加算演算
    public string Add(
        char value,
        char value1 )
    {
        Tuple<bool, char> result = this.Operator(
            value,
            value1,
            ( char v ) => this.increment( v ) );
        if ( result.Item1 ) return "1" + result.Item2;
        else return result.Item2.ToString( );
    }

    //減算演算
    public string Sub(
        char value,
        char value1 )
    {
        Tuple<bool, char> result = this.Operator(
            value,
            value1,
            ( char v ) => this.Decrement( v ) );
        if ( result.Item1 ) return "-" + result.Item2;
        else return result.Item2.ToString( );
    }
}

プログラムを読めば、足し算や引き算すら思いのほか複雑だと分かってもらえると思います。プロは実装できて当然でしょうが、おそらく初心者は無理なのでは?
 私の持論は、「実装できないものは理解できていない」です。足し算や引き算が良い例です。私は幼いころ、どうしても1+1=2の原理が気になりました。私は実装できるレベルの知識がほしかったのです。暗記したからと言って、その物事を理解しているといえません。他にも、電話や飛行機も私にとっては不思議です。これを言うと当たり前だと嘲る人が居ますが、私は自分がそれらを作れるほど知らないので、素直にわかっていないと考えているだけです。飛行機が当たり前の存在だという人は、飛行機を自分の手で作れるのでしょうか?私はそう見えません。それらの人が航空力学や機械工学などをマスターしているようには見えません.。暗記しかしておらず、自分で作れないものを理解しているとは言えないと思います。
 こうやって改めて考えると、身の回りのものは不思議なものだらけです。疑問にすら感じなかったり、理解していると考えている人が多いようですが、私はそれらを作れるほど知らないので、自分は無知だといつも思っています。足し算や引き算ですらこの行数のプログラムが必要なのですから、飛行機や電話を電気レベルで実装するとなると、いったいどれだけ必要なのかわかりません。
 さらに言うならば、人間や宇宙を完全に実装できません。私はまだまだ未熟者です。本当にプログラミングをマスターしているならば、この世のあらゆるものを実装できるでしょう。凡人の私がその境地に至るのは不可能でしょうが、それを目指して日々精進しています。
 みんなも時間が空いたときに、普段当たり前だと考えている物事の実装を試みませんか?きっと楽しい時間を送れると思います。

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき160 - 本当の不景気解決法

 選挙時のニュースを聞いていて、日本が不景気な根本的理由と解決法がわかっていないなと感じたので書くことにしましました。私たち情報技術者から見れば、日本が不景気な根本的理由と、その解決方法は明確です。OSともいえる日本の国家システムがまるで出鱈目だからです。
 情報技術の観点から見れば、国家システムとは、日本内のリソースを管理するOSのようなものです。もちろん国家システムの場合、リソースを管理するだけではなく、法律を生産する機能も必要となります。しかしながら、この2つともまるで駄目です。残念ながら、システムとすら呼べない代物です。
 国家システムのリソース管理機能と言えば、お金と資源なのですが、復興予算で浪費されたり、天下り法人に浪費されたり、私利私欲で貴重なリソース(お金、時間、国民の命)などが失われています。また、法律生産機能に関しても、明らかに問題発生件数よりも生産能力が低いのが見て取れます。年金問題や復興問題など問題が増えるばかりです。日本は戦後60年以上もたつのにも関わらずこの状態です。日本人として情けない限りです。
 そもそも、あのような原始的な手段で、選挙をする意味が分かりません。おまけに政治家の人数が固定なのが論理的ではありません。状況は刻一刻変わります、必要な人数だけ、予算に応じて雇える形にするのが当然ですし、バザール方式で民間人が法律を作ってもよいのです。政治などの一部の人に立法を任せておくと、自分にとって不利な法律を立法しない(自分を律する法律を作らない)だという問題があります。いまだに何をしても逮捕されないのがその証拠です。
 この状況下で得をするのは、犯罪行為をしたい人だけです。真面目な政治家にとっても、こんなひどいシステムの中で働きたくはないでしょう。何故ならば、犯罪行為もしくは、悪いことをした方が得をするのですから、真面目に働くのがばからしくなるでしょうし、犯罪的な妨害行為をされる危険性もあるからです。まともな管理システムがないので、事実上クラッキング(破壊行為)をしたい放題です。犯罪者や悪い人にとって天国ではないでしょうか。正直者は馬鹿を見るとはよくいったものですが、普通システムは、悪いことは遣りにくく、正しいことはやりやすくするものです。日本の場合全くの逆です。
 日本の国家システムの現状をわかりやすくというと、セキュリティゼロで、ウイルス感染しまくり、のぞき見され放題、リソース盗まれ放題、なおかつ再起動もできないPCです。こんなPCを使いたい人はいません。喜ぶのはそんなPCに対して犯罪項をしたい人だけではないでしょうか?
 不景気なのも国家システムがまるで駄目だからです。むろん一時的に不景気になることはあるでしょう。しかしながら、システムさえまともならば、我々国民が頑張って景気をよくします。戦後日本が復興したのも、政府のおかげではなく、私たち国民の努力の結果です。どちらかというと、足を引っ張り続けているように思えてなりません。日本は国家システムさえまともならば、世界1の経済国家になりうる潜在能力を持っていると思います。まぁこれは、私が日本人だからそう思うのかもしれませんが、戦後急激に復興したことからわかるように、潜在能力は他の先進国に引けを取らないと思います。従って、政治家が経済をうんぬんするなんてことは見当違いだと私は思えてなりません。国民も政治家にそのような事を期待せず、経済は自分たちがするから、まともな法律を黙々と作ってくれというべきです。
 改めて考えてみれば、本来政治家は立法家であるべきですが、私たち国民も芸能人のような扱いをしたり、経済をどうにかしかてくれなどと役割違いな要求をしています。政治家の仕様が定まっていません。役割そのものがあいまいなので、その人たちが作っている、国家システムも酷いのでしょう。
 この問題はだれが悪いというレベルの問題ではありません。私たち日本人全員が悪いのです。自分たちの国家システムを考えない時点で、他国の人々に笑われても仕方がありません。自分たちの国は自分たちで考える。そんな子供でも分かる当たり前のことを、戦後60年以上放棄し続けた結果がこのざまです。日本はすでに先進国ではなく、後進国と言ってもよいぐらいかもしれません。思考停止して、空気で生きていければ苦労はしませんが、自然界は厳しく、そんなことをしていれば、日本そのものがなくなるでしょう。その時、想定外でしたでは済まされません。国を失った民族がどうなるのかは、歴史が証明しています。悲劇が訪れてからは取り返しがつかないので、考えるべきことは考えるべきなのではないでしょうか?

テーマ : 文明・文化&思想
ジャンル : 学問・文化・芸術

C#文法リファレンス - ローカル変数

概要
 局所的に使用する変数を定義します。

日常でたとえると
 そこら辺にある紙片を使って、計算をしたりメモをしたりする事。

使用に適した状況
 変数を使用したい場合、最優先に採用を考えるべき変数です。プログラミングでは、なるべく局所的範囲内でのみ値を使用し、更新時の負担を減らすのがベストです。

サンプル

/*----------------------------------------------------
 * 
 *  ローカル変数
 *  
 ----------------------------------------------------*/
using System;

class Sample
{
    static void Main()
    {
        //ローカル変数を定義
        int x = 10;

        //値を表示
        Print( );
        Print( x );

        //終了
        Console.ReadLine( );
    }

    //ローカル変数の値は共有されない
    static void Print()
    {
        int x = 20;
        Console.WriteLine( "同名のローカル変数Xの値は{0}です。", x );
    }

    //呼び出し時に渡すと使える
    static void Print( int x )
    {
        Console.WriteLine( "ローカル変数Xの値は{0}です。", x );
    }
}


文法
 メンバーの波括弧内で、型名、変数名の順で記述します。初期値を設定することも可能なので、できる限り変数を宣言するときに値を代入しておきましょう。

解説
 変数には色々な種類があり、使用できる範囲に応じて変数が用意されています。そのうち最も使用できる範囲が狭いのが、今回紹介するローカル変数です。
 ローカル変数は、別種の変数であるフィールド(インスタンス変数)とは違い、メソッド間で共有できません。どうしても値を使用したい場合は、フィールドを使用するか、メソッドを呼び出すときに渡すようにします。
 使用できる範囲というのは、簡単に言うと、変数の値を共有できる場所の事です。ローカル変数はメソッド内でのみ使用でき、違うメソッド内にある同名の変数とは違う値を持つと見做されます。日常でローカル変数をたとえると、いらない紙の端や裏に、その場限りのメモ書きするようなものです。
 値が共有できる範囲が狭いというと、あまりよく聞こえませんが、実は一番多用する変数です。何故ならば、プログラミングでは極力、他のプログラムに影響を与えないようにするのがベストだからです。もしプログラムの影響範囲が広ければ、変更する際に参照している側のプログラムまで変更しなければならなくなるので、極力狭い範囲で値を使用できるようにした方が良いのです。この理由から、熟練者ほどローカル変数を使用します。

テーマ : プログラミング
ジャンル : コンピュータ

C#文法リファレンス - フィールド / インスタンス変数

概要
 各オブジェクトは、個々に値を持つことができます。それらのオブジェクトを構成する各種の値をフィールドもしくはインスタンス変数と呼びます。

日常でたとえると
 人は皆、名前、身体的特徴、性格などが違います。それら個別の値の事。

使用に適した状況
 オブジェクトに何らかの値を持たせたい場合。

サンプル

/*----------------------------------------------------
 * 
 *  フィールド / インスタンス変数
 *  
 ----------------------------------------------------*/
using System;

class Foo
{
    //通常はこうする
    int fieldValue;

    //外部に公開したら駄目!
    public int BadField;

    //コンストラクタに渡される値から導出
    public Foo( int value )
    {
        this.fieldValue = value * 2;
    }

    //Fieldを確認するのはメソッド
    public void PrintValue()
    {
        Console.WriteLine( "インスタンスの値:{0}",
            this.fieldValue);
    }

    static void Main()
    {
        //Fieldの値を確認してみる
        Foo obj = new Foo( 10 );
        obj.PrintValue( );
    }
}


文法
 参照型もしくは値型の波括弧内で、アクセス修飾子、型名、名前の順に記述します。アクセス修飾子は通常は指定せず、デフォルトのprivateにしておきます。

解説
 大半のオブジェクトは、何らかの値を持っています。それらオブジェクトの構成物である値の事を、フィールドもしくはインスタンス変数と呼びます。インスタンス変数はもともと、smalltalkというプログラミング言語の用語で、オブジェクトの属性を表わしています。属性と言っても、ニュアンスが違うもののオブジェクトが持つ値とほぼ同じ概念です。
 フィールドは通常外部に公開せず、何らかの処理をして導出します。そして、型が持つメソッド内で使用されます。これは、オブジェクト指向プログラミングの情報の隠蔽の原則によるものです。オブジェクトの詳細な実装を気にせずに扱えるようにするのが、オブジェクト指向プログラミングの基本です。従って、よほど特別な理由がない限り、フィールドにpublic修飾子をつけて外部に公開しないでください。
 外部に公開せず内緒で値を持つことには意味があります。細かい実装は時が経つにつれて変更される場合が多々あります。その時、もし外部に公開していれば、変更による影響が大きくなってしまいます。極力他のオブジェクトに影響を与えず、自由に実装の詳細を変えられるようにしておけば、余計な雑務から解放されます。

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき159 - 選挙から見える専門家と非専門家の役割分担の在り方

 ここ最近、選挙の話題が占めています。選挙システムは、お話にならないほど酷いものですが、いまだに選んだ国民が悪いだとか、参加しない国民が悪いなどと低レベルな話しがされています。それをきっかけに今回は、専門家と非専門家のかかわり方について書こうと思いました。
 選挙システムに参加する人の役割は、政治家(専門家)と非専門家(国民)です。選挙に限らず、我々日本人はどうも、この専門家と非専門家の役割分担が下手なように思えてなりません。というのも、非理論的に感情だけを並べ立てるだけだからです。
 これはIT業界にも共通していえる事ですが、非専門家は過程や表面的な事に拘りすぎで、専門分野がわからないから無関心になったり、見当違いの要求をしたり、「お客様は神様だ」と過剰要求をしがちです。一方専門家側も、専門分野を知らない人が何を言っていると馬鹿にしがちです。それは、衆愚政治などという発言がある事からも伺えます。また、専門分野において私は正しいから、非専門家がいう事は正しくないといいがちです。政治家や官僚はよく、私は成功したと思ったから良いだとか言って責任と採りません。民間企業も想定外でしたなどと責任回避をします。さらには、政治に至っては、「選んだあなたが悪い」という人さえいます。日本の非専門家は見当違いな感情論に終始し、専門家もまた非理論的な言い訳に終始して結果責任を取りません。これはどう考えても病的でおかしな関係です。もっと健全な関係を模索するべきではないでしょうか?
 私はシステム屋ですので、常に情報技術の非専門家(お客様)との良好な関係を模索しており、完璧ではないものの一つの方策を持っています。それは、両者の性質をよく考えて、相応しい役割を果たすという方法です。
 具体例を挙げます。私はお客様に、望む結果、予算、納期の3点を問いかけます。一方お客様には、この3点をチェックしてもらいます。非専門家であるお客様が、システム開発の方法を言えば間違っている可能性は極めて高いですが、システム開発の結果(結果、予算、納期)はお客様が判断するべきことです。従って私は、仕事のやり方には干渉させませんが、システムの評価についてはお客様にゆだねます。どれほど学術的に最高のシステムを作っても、お客様が無価値だと思えば無価値なのです。むろん、明らかな難癖は論外です。日本は役割を論理的に区別しないで、ちゃんとやっている空気を醸しているだけなので、モンスタークレーマーや一種の詐欺行為に弱いのではないでしょうか?
 そろそろ話を締めます。専門的な過程については、専門家がやるべきことです。しかしながら、結果の評価に関しては、それを要求する非専門家にゆだねるべきです。決して、専門分野を知らない人が悪いなどと言ってはいけません。これがまかり通る、もしくはこの関係が続くならば、医学の知識がない人は病院へ行けず、建築技術について熟知していない人は安心して家を購入できないなどといったことになりえます。そのような病的な関係を空気で作らないで、双方の役割分担を論理的に考え、ともに喜びあえる健全な関係を築くべきではないでしょうか?

テーマ : 文明・文化&思想
ジャンル : 学問・文化・芸術

C#文法リファレンス - 値を返すメソッド

概要
 C#で標準的なやり方である、オブジェクト指向プログラミングでは、プログラムをほどよい分量に分けるために、メソッドという概念があります。このメソッドをてぎすると、実行するプログラム(オブジェクトの振る舞い)を定義することができます。
 今回はメソッドのうち、値を返すものを解説しています。値を返すメソッドは、関数とも呼ばれます。

使用に適した状況
 常に使用するべきです。整理整頓は大切です。

日常でたとえると
 誰かに仕事や用事を頼むとき、仕事や用事の結果を教えてもらう事。

サンプル

/*----------------------------------------------------
 * 
 *  値を返すメソッド
 * 
 ----------------------------------------------------*/
using System;

//参照型はメソッドを持てる
class ReferenceType
{
    //値を返すメソッド(関数)
    public int Function( int value )
    {
        return value;
    }
}

//値型もメソッドを持てる
struct ValueType
{
    //値を返すメソッド(関数)
    public int Function( int value )
    {
        return value;
    }
}

class Sample
{
    static void Main()
    {
        //値を返すメソッドを呼び出す。
        ReferenceType obj = new ReferenceType( );
        Console.WriteLine( "値を返すメソッドを呼び出します。" );
        Console.Write( "戻り値は" );
        Console.WriteLine( obj.Function( 100 ) );
        
        //終了
        Console.ReadLine( );
    }
}


文法
 アクセス修飾子、返す値の型、メソッドの名前、丸括弧(受け取る値)の順に書きます。受け取る値とは、メソッドを呼び出すときに指定する値の事です。詳しくは別の記事で解説します。
 最終的に返す値は、returnキーワードと値を組で指定します。値の部分には変数、計算式、他の値を返すメソッドの呼び出しを指定できます。

解説
 ちょっとしたアプリケーションや本格的なソフトウェアを作りたいとき、大量のプログラムが必要となります。この大量のプログラムは、実務的なものでは万行単位になります。実務的とまではいかないまでも、ちょっとしたアプリケーションでも数百行は必要となるでしょう。もし仮に、短く済むコマンドアプリケーションを作りたい場合でも、将来の事を考えると、綺麗に整理整頓したほうが良いでしょう。
 大量のプログラムを扱う方法のうちの一つとして、プログラムの塊に名前を付けて定義する方法があります。そのプログラムの塊をメソッドと呼びます。メソッドには2種類あります。そのうちの一つが、値を返すメソッドです。
 値を返すメソッドは、指定された値から適切な値を導き出します。足し算や引き算をイメージすると分かりやすいと思います。プログラミングをしていると、何らかの値を導き出したいことが多々あります。プログラミングをしてみると、よくわかると思います。
 なお型とは、メソッドの集まりに名前をつけたものと考えるとよいでしょう。厳密には違いますが、ひとまずそう考えるとイメージしやすいです。

テーマ : プログラミング
ジャンル : コンピュータ

C#文法リファレンス - 値を返さないメソッドを定義

概要
 C#で標準的なやり方である、オブジェクト指向プログラミングでは、プログラムをほどよい分量に分けるために、メソッドという概念があります。このメソッドをてぎすると、実行するプログラム(オブジェクトの振る舞い)を定義することができます。
 今回はメソッドのうち、値を返さないものを解説しています。値を返さないメソッドは、サブルーチンとか、プロシージャ(手続き)とも呼ばれます。

日常でたとえると
 誰かに何かを頼むとき、その結果を気にしないときがあります。それが、戻り値がないメソッドのイメージです。

使用に適した状況
 プログラムをきれいに整理整頓するために、常に使用するべきです。

サンプル
/*----------------------------------------------------
 * 
 *  値を返さないメソッド(サブルーチン)
 *   「サブルーチン」もしくは
 *   「プロシージャ(手続き)」   
 *   とも呼ばれる
 * 
 ----------------------------------------------------*/
using System;

//参照型はメソッドを持てる
class ReferenceType
{
    //値を何も返さないメソッド(サブルーチン)
    public void Sub()
    {
        Console.WriteLine( "参照型のメソッドです。" );
        Console.WriteLine( "値は返しません" );
    }
}

//値型もメソッドを持てる
struct ValueType
{
    //値を何も返さないメソッド(サブルーチン)
    public void Sub()
    {
        Console.WriteLine( "値型のメソッドです。" );
        Console.WriteLine( "値は返しません" );
    }
}

class Sample
{
    static void Main()
    {
        //値を返さないメソッドを呼び出す
        ReferenceType obj = new ReferenceType( );
        obj.Sub();

        //終了
        Console.ReadLine( );
    }
}



文法
 アクセス修飾子、「void」キーワード、メソッドの名前、丸括弧(受け取る値)の順に書きます。受け取る値とは、メソッドを呼び出すときに指定する値の事です。詳しくは別の記事で解説します。

解説
 ちょっとしたアプリケーションや本格的なソフトウェアを作りたいとき、大量のプログラムが必要となります。この大量のプログラムは、実務的なものでは万行単位になります。実務的とまではいかないまでも、ちょっとしたアプリケーションでも数百行は必要となるでしょう。もし仮に、短く済むコマンドアプリケーションを作りたい場合でも、将来の事を考えると、綺麗に整理整頓したほうが良いでしょう。
 大量のプログラムを扱う方法のうちの一つとして、プログラムの塊に名前を付けて定義する方法があります。そのプログラムの塊をメソッドと呼びます。メソッドには2種類あります。そのうちの一つが、値を返さないメソッドです。
 値を返さないのであれば、なんでそんなものが必要なのかと疑問に思う方もいるでしょう。それは、型が持つ各種の値を処理したり、機械に何らかの動作をさせるためです。
 通常、値を返さないメソッドは、使用者が見えない所で何らかの処理をします。ですから、使用者に詳細を見せたくない場合は、値を返さないメソッドを定義しましょう。
 なお型とは、メソッドの集まりに名前をつけたものと考えるとよいでしょう。厳密には違いますが、ひとまずそう考えるとイメージしやすいです。

テーマ : プログラミング
ジャンル : コンピュータ

C#文法リファレンス - クラスの継承(子クラスを定義)

概要
 既存の型を拡張した、新しい型を定義します。この時既存の型として指定する肩を親クラス、新しい型の方を子クラスと呼びます。子クラスは何のプログラムを書かなくとも、親クラスの定義(メンバーや仕様)は全て持っています。

日常でたとえると
 動物はみな動きます。人間は動く、ネズミは動く、猫は動く...とか、いちいち動物の基本性質の事を言いません。それをプログラミングの世界では継承と呼びます。

使用に適した状況
 既存のプログラムを極力保持したままで、提供する機能を増やしたい場合。

サンプル

/*----------------------------------------------------
 * 
 *  クラスの継承
 *  
 ----------------------------------------------------*/
using System;

class Parent
{
    public void Print()
    {
        Console.WriteLine( "親クラスのメソッドです。" );
    }
}

class Child : Parent
{
}

class Sample
{
    static void Main()
    {
        //親クラスのメソッドは必ず備えている
        //親ができる事は子もできる
        Child obj = new Child( );
        obj.Print( );
    }
}


文法
 クラス名、「:」(コロン記号)、親クラスの名前の順に記述します。

解説
 オブジェクト指向プログラミングの目的のうちの1つは、既存のプログラムをそのままにしながら提供できる機能を増やすことです。この目的を実現するのが継承です。クラスの継承は、既存のクラスを拡張し、プログラムの再利用性を高めます。
 どうやって既存のプログラムを変えないで機能を増やすのかというと、型の振る舞い(動作や機能の事)を保証することによってなされます。既存のプログラムと同様の事が実行できればプログラムを変える必要はありません。この考え方から、子とされたクラスは、何も書かずとも、親クラスができる事(備えているメンバー)は全て持っています。さらに、子クラスは親クラスを拡張するものであり、新しいメンバーを追加することができます。これにより、既存の極力プログラムを変えないで、新しい機能を追加することが可能となります。
 ただし、子クラスが親クラスの特徴を継承するからと言って、面倒だから子クラスにしてしまうという安易な考えは駄目です。親クラスができる事をすべて子クラスができるという事は、先ほど言ったように、クラスの継承は親クラスの保証をも引き継ぐことを意味しています。従って、子クラスは親クラスが保障することは全て保障せねばなりません。
 もし、一部のプログラムを採用したいものの、保証は継承できないのであれば、子として定義するのではなく、内部でほしい機能を持ったオブジェクトを使用しましょう。

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター