C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: べき算「^」を追加するには?


(過去ログ 58 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■33335 / inTopicNo.1)  べき算「^」を追加するには?
  
□投稿者/ 構文解析 (1回)-(2009/02/26(Thu) 09:47:52)

分類:[C#] 

構文解析をC#で書いてみました。
べき算「^」を追加するには何処に触ればいいのか
アドバイスを下さい。

using System;

namespace ConsoleApplication1 {
    class Program {
        static void Main( string[] args ) {
            構文解析 o構文解析 = new 構文解析();
            string[] s計算式 = new string[] { 
                "(.1+45/0.5)*2+3",
                "sin(4 + 13 * 2) * tan(45)",
                "sqr(sin(4 + 13 * 2) * tan(45) * 2 )",
                "-2 + 1"
            };
            double 答;
            foreach ( string s式 in s計算式 ) {
                答 = o構文解析.計算( s式 );
                System.Console.WriteLine( s式 + " = " + 答.ToString() );
            }
        }
    }

    public class 構文解析 {

        private string m_s計算式;
        private int    m_i計算位置;
        private const double 円定数 = Math.PI / 180.0;


        public double 計算( string s計算式_ ) {
            m_s計算式 = s計算式_.ToUpper().Replace(" ","");
            m_i計算位置 = 0;
            try {
                return 式();
            } catch ( Exception e ) {
                System.Console.WriteLine( e.ToString() );
                return double.NaN;
            }
        }

        private double 式() {
            double 答 = 項();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '+': m_i計算位置++; 答 += 項(); break;
                    case '-': m_i計算位置++; 答 -= 項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 項() {
            double 答 = 因子();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '*': m_i計算位置++; 答 *= 項(); break;
                    case '/': m_i計算位置++; 答 /= 項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 因子() {
            double 答;
            if ( m_s計算式[m_i計算位置] == '(' ) {
                m_i計算位置++;
                答 = 式();
                if ( m_s計算式[m_i計算位置] != ')' ) throw new Exception(")なし");
                m_i計算位置++;
            } else {
                答 = 数値();
            }
            return 答;
        }

        private double 数値() {
            double 答 = double.MinValue;
            char 符号 = '+';
            switch ( m_s計算式[m_i計算位置] ) {
                case '+': 符号 = m_s計算式[m_i計算位置++]; break;
                case '-': 符号 = m_s計算式[m_i計算位置++]; break;
            }
            if ( Is数値文字(m_s計算式[m_i計算位置]) == true ) {
                string s数値 = string.Empty;
                for ( ; m_i計算位置 < m_s計算式.Length; ) {
                    if ( Is数値文字(m_s計算式[m_i計算位置]) == false ) break;
                    s数値 += m_s計算式[m_i計算位置++];
                }
                try {
                    答 = double.Parse(s数値);
                } catch ( Exception e ) {
                    throw e;
                }
            } else {
                int iLen = 0;
                if ( m_i計算位置 + 3 < m_s計算式.Length ) {
                    string s関数 = m_s計算式.Substring(m_i計算位置 ,3);
                    switch ( s関数 ) {
                        case "SIN": m_i計算位置 += 4; 答 = Math.Sin(円定数 * 式()); m_i計算位置++; break;
                        case "COS": m_i計算位置 += 4; 答 = Math.Cos(円定数 * 式()); m_i計算位置++; break;
                        case "TAN": m_i計算位置 += 4; 答 = Math.Tan(円定数 * 式()); m_i計算位置++; break;
                        case "SQR": m_i計算位置 += 4; 答 = Math.Sqrt(式()); m_i計算位置++; break;
                    }
                }
            }
            if ( 符号 == '-' ) return -答;
            return 答;
        }

        private bool Is数値文字( char 文字 ) {
            if ( char.IsDigit( 文字 ) == true ) return true;
            if ( 文字.Equals('.') == true ) return true;
            return false;
        }
    }

}

引用返信 編集キー/
■33336 / inTopicNo.2)  Re[1]: べき算「^」を追加するには?
□投稿者/ επιστημη (1784回)-(2009/02/26(Thu) 10:00:59)
επιστημη さんの Web サイト
> べき算「^」を追加するには何処に触ればいいのか
'*' '/' と同じとこでいんじゃないすか?
二項演算だし、優先順位は+-より高いでしょから。

引用返信 編集キー/
■33342 / inTopicNo.3)  Re[2]: べき算「^」を追加するには?
□投稿者/ 構文解析 (2回)-(2009/02/26(Thu) 10:48:16)
> '*' '/' と同じとこでいんじゃないすか?
> 二項演算だし、優先順位は+-より高いでしょから。
にすると
((4*2)^2)/2 = 32
4*2^2/2 = 8
となります。'^'の優先順位を'*' '/'より上げたい場合は如何したら好いでしょうか?

 using System;

namespace ConsoleApplication1 {
    class Program {
        static void Main( string[] args ) {
            構文解析 o構文解析 = new 構文解析();
            string[] s計算式 = new string[] { 
                "(.1+45/0.5)*2+3",
                "sin(4 + 13 * 2) * tan(45)",
                "sqr(sin(4 + 13 * 2) * tan(45) * 2 )",
                "((4*2)^2)/2",
                "4*2^2/2"
            };
            double 答;
            foreach ( string s式 in s計算式 ) {
                答 = o構文解析.計算( s式 );
                System.Console.WriteLine( s式 + " = " + 答.ToString() );
            }
        }
    }

    public class 構文解析 {

        private string m_s計算式;
        private int    m_i計算位置;
        private const double 円定数 = Math.PI / 180.0;


        public double 計算( string s計算式_ ) {
            m_s計算式 = s計算式_.ToUpper().Replace(" ","");
            m_i計算位置 = 0;
            try {
                return 式();
            } catch ( Exception e ) {
                System.Console.WriteLine( e.ToString() );
                return double.NaN;
            }
        }

        private double 式() {
            double 答 = 項();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '+': m_i計算位置++; 答 += 項(); break;
                    case '-': m_i計算位置++; 答 -= 項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 項() {
            double 答 = 因子();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '^': m_i計算位置++; 答 = Math.Pow(答 ,項()); break;
                    case '*': m_i計算位置++; 答 *= 項(); break;
                    case '/': m_i計算位置++; 答 /= 項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 因子() {
            double 答;
            if ( m_s計算式[m_i計算位置] == '(' ) {
                m_i計算位置++;
                答 = 式();
                if ( m_s計算式[m_i計算位置] != ')' ) throw new Exception(")なし");
                m_i計算位置++;
            } else {
                答 = 数値();
            }
            return 答;
        }

        private double 数値() {
            double 答 = double.NaN;
            char 符号 = '+';
            switch ( m_s計算式[m_i計算位置] ) {
                case '+': 符号 = m_s計算式[m_i計算位置++]; break;
                case '-': 符号 = m_s計算式[m_i計算位置++]; break;
            }
            if ( Is数値文字(m_s計算式[m_i計算位置]) == true ) {
                string s数値 = string.Empty;
                for ( ; m_i計算位置 < m_s計算式.Length; ) {
                    if ( Is数値文字(m_s計算式[m_i計算位置]) == false ) break;
                    s数値 += m_s計算式[m_i計算位置++];
                }
                try {
                    答 = double.Parse(s数値);
                } catch ( Exception e ) {
                    throw e;
                }
            } else {
                if ( m_i計算位置 + 3 < m_s計算式.Length ) {
                    string s関数 = m_s計算式.Substring(m_i計算位置 ,3);
                    switch ( s関数 ) {
                        case "SIN": m_i計算位置 += 4; 答 = Math.Sin(円定数 * 式()); m_i計算位置++; break;
                        case "COS": m_i計算位置 += 4; 答 = Math.Cos(円定数 * 式()); m_i計算位置++; break;
                        case "TAN": m_i計算位置 += 4; 答 = Math.Tan(円定数 * 式()); m_i計算位置++; break;
                        case "SQR": m_i計算位置 += 4; 答 = Math.Sqrt(式()); m_i計算位置++; break;
                    }
                }
            }
            if ( 符号 == '-' ) return -答;
            return 答;
        }

        private bool Is数値文字( char 文字 ) {
            if ( char.IsDigit( 文字 ) == true ) return true;
            if ( 文字.Equals('.') == true ) return true;
            return false;
        }
    }

}

引用返信 編集キー/
■33343 / inTopicNo.4)  Re[3]: べき算「^」を追加するには?
□投稿者/ επιστημη (1786回)-(2009/02/26(Thu) 11:00:15)
επιστημη さんの Web サイト
> '^'の優先順位を'*' '/'より上げたい場合は如何したら好いでしょうか?

構文規則を変更すりゃいいでしょう。

引用返信 編集キー/
■33344 / inTopicNo.5)  Re[3]: べき算「^」を追加するには?
□投稿者/ よねKEN (276回)-(2009/02/26(Thu) 11:02:58)
2009/02/26(Thu) 11:26:08 編集(投稿者)

> となります。'^'の優先順位を'*' '/'より上げたい場合は如何したら好いでしょうか?

項と因子の間にべき乗のための新たな構文定義を追加しましょう。

<追記>
-2^2は、4、-4のどちらと解釈しますか?
4と解釈する場合は、単項演算子の+/-よりも優先順位を高くする必要があります。
上記の「項と因子の間に」の回答の方針では、-4になるパターンです。
</追記>
引用返信 編集キー/
■33347 / inTopicNo.6)  Re[1]: べき算「^」を追加するには?
□投稿者/ よねKEN (277回)-(2009/02/26(Thu) 11:16:50)
質問とは関係ないですが、ちょっと気になったので、蛇足かもしれませんがコメントします。

"(.1+45/0.5)*2+3"というサンプルを少し変更して、"-(.1+45/0.5)*2+3"だと計算がうまく行きません。
こういうのにも対応したいなら、単項演算子の+/-の処理は、因子でやるように構文規則を変えるといいですよ。
引用返信 編集キー/
■33354 / inTopicNo.7)  Re[2]: べき算「^」を追加するには?
□投稿者/ 構文解析 (3回)-(2009/02/26(Thu) 12:41:10)
> "(.1+45/0.5)*2+3"というサンプルを少し変更して、"-(.1+45/0.5)*2+3"だと計算がうまく行きません。
> こういうのにも対応したいなら、単項演算子の+/-の処理は、因子でやるように構文規則を変えるといいですよ。
下記の変更でいいでしょうか?
他にも、お気づきのてんがあれば、お知らせ下さい。

using System;

namespace ConsoleApplication1 {
    class Program {
        static void Main( string[] args ) {
            構文解析 o構文解析 = new 構文解析();
            string[] s計算式 = new string[] { 
                "-2^2",
                "-(.123+.456)",
                "4*2^2",
                "(4*2)^2",
                "((4*2)^2)/2",
                "4*2^2/2"
            };
            double 答;
            foreach ( string s式 in s計算式 ) {
                答 = o構文解析.計算( s式 );
                System.Console.WriteLine( s式 + " = " + 答.ToString() );
            }
        }
    }

    public class 構文解析 {

        private string m_s計算式;
        private int    m_i計算位置;
        private const double 円定数 = Math.PI / 180.0;


        public double 計算( string s計算式_ ) {
            m_s計算式 = s計算式_.ToUpper().Replace(" ","");
            m_i計算位置 = 0;
            try {
                return 式();
            } catch ( Exception e ) {
                System.Console.WriteLine( e.ToString() );
                return double.NaN;
            }
        }

        private double 式() {
            double 答 = 項();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '+': m_i計算位置++; 答 += 項(); break;
                    case '-': m_i計算位置++; 答 -= 項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 項() {
            double 答 = 冪乗項();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '*': m_i計算位置++; 答 *= 冪乗項(); break;
                    case '/': m_i計算位置++; 答 /= 冪乗項(); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 冪乗項() {
            double 答 = 因子();
            for ( ; m_i計算位置 < m_s計算式.Length; ) {
                switch ( m_s計算式[m_i計算位置] ) {
                    case '^': m_i計算位置++; 答 = Math.Pow(答 ,因子()); break;
                    default: return 答;
                }
            }
            return 答;
        }

        private double 因子() {
            double 答;
            char 符号 = '+';
            switch ( m_s計算式[m_i計算位置] ) {
                case '+': 符号 = m_s計算式[m_i計算位置++]; break;
                case '-': 符号 = m_s計算式[m_i計算位置++]; break;
            }
            if ( m_s計算式[m_i計算位置] == '(' ) {
                m_i計算位置++;
                答 = 式();
                if ( m_s計算式[m_i計算位置] != ')' ) throw new Exception(")なし");
                m_i計算位置++;
            } else {
                答 = 数値();
            }
            if ( 符号 == '-' ) return -答;
            return 答;
        }

        private double 数値() {
            double 答 = double.NaN;
            if ( Is数値文字(m_s計算式[m_i計算位置]) == true ) {
                string s数値 = string.Empty;
                for ( ; m_i計算位置 < m_s計算式.Length; ) {
                    if ( Is数値文字(m_s計算式[m_i計算位置]) == false ) break;
                    s数値 += m_s計算式[m_i計算位置++];
                }
                try {
                    答 = double.Parse(s数値);
                } catch ( Exception e ) {
                    throw e;
                }
            } else {
                if ( m_i計算位置 + 3 < m_s計算式.Length ) {
                    string s関数 = m_s計算式.Substring(m_i計算位置 ,3);
                    switch ( s関数 ) {
                        case "SIN": m_i計算位置 += 4; 答 = Math.Sin(円定数 * 式()); m_i計算位置++; break;
                        case "COS": m_i計算位置 += 4; 答 = Math.Cos(円定数 * 式()); m_i計算位置++; break;
                        case "TAN": m_i計算位置 += 4; 答 = Math.Tan(円定数 * 式()); m_i計算位置++; break;
                        case "SQR": m_i計算位置 += 4; 答 = Math.Sqrt(式()); m_i計算位置++; break;
                    }
                }
            }
            return 答;
        }

        private bool Is数値文字( char 文字 ) {
            if ( char.IsDigit( 文字 ) == true ) return true;
            if ( 文字.Equals('.') == true ) return true;
            return false;
        }
    }

}

引用返信 編集キー/
■33362 / inTopicNo.8)  Re[3]: べき算「^」を追加するには?
□投稿者/ よねKEN (278回)-(2009/02/26(Thu) 16:19:12)
No33354 (構文解析 さん) に返信
> > "(.1+45/0.5)*2+3"というサンプルを少し変更して、"-(.1+45/0.5)*2+3"だと計算がうまく行きません。
>>こういうのにも対応したいなら、単項演算子の+/-の処理は、因子でやるように構文規則を変えるといいですよ。
> 下記の変更でいいでしょうか?

私のコメントの意図はそういうことであってます。
プログラムが期待通りかどうかについてはテストして確認してください。
引用返信 編集キー/
■33368 / inTopicNo.9)  Re[3]: べき算「^」を追加するには?
□投稿者/ επιστημη (1789回)-(2009/02/26(Thu) 16:36:29)
επιστημη さんの Web サイト
> 他にも、お気づきのてんがあれば、お知らせ下さい。

ベキは右結合? 左結合?
3^3^3 は 3^(3^3) それとも (3^3)^3 ?

# どっちでもいいけど。仕様/期待通りの結果が出れば。

引用返信 編集キー/
■33369 / inTopicNo.10)  Re[4]: べき算「^」を追加するには?
□投稿者/ 構文解析 (4回)-(2009/02/26(Thu) 16:37:55)
No33362 (よねKEN さん) に返信
> ■No33354 (構文解析 さん) に返信
>>> "(.1+45/0.5)*2+3"というサンプルを少し変更して、"-(.1+45/0.5)*2+3"だと計算がうまく行きません。
> >>こういうのにも対応したいなら、単項演算子の+/-の処理は、因子でやるように構文規則を変えるといいですよ。
>>下記の変更でいいでしょうか?
>
> 私のコメントの意図はそういうことであってます。
> プログラムが期待通りかどうかについてはテストして確認してください。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -