- PR -

計算式の文字列を計算する方法は?

1
投稿者投稿内容
maru
常連さん
会議室デビュー日: 2001/10/09
投稿数: 23
投稿日時: 2003-08-01 11:27
1+(2*3)
といった文字列を計算する方法、クラス、コントロールはあるのでしょうか?

Windowsの計算機では文字列の貼付けを行うことで計算してくれるのですが
プログラムから計算式を与え答えを取得する方法がわからなかったので
そういった機能のクラスなどがあるのかなと探しています。
Beatle
ぬし
会議室デビュー日: 2003/06/09
投稿数: 394
投稿日時: 2003-08-01 13:15
多分無いと思います。(あったらゴメンナサイ)

計算式をデータとして捕らえて、それを計算するというのはよく要件としてあるので
すが、単純にはできないのです。
コンパイラの作成等ではよく使われる逆ポーランド記法なんかを調べてみて、自作す
るしかないかもしれません。
WEB上で検索すればサンプルソース等見つかるかもしれませんよ。
ちなみに、http://www.sado.co.jp/system/taka/Calc/default.htm
のソース等は参考になるかも。
TomScissors
ベテラン
会議室デビュー日: 2003/06/05
投稿数: 79
投稿日時: 2003-08-01 13:18
Windowsの計算機は、
文字列の貼り付けを行うとプログラム側で一文字づつ文字列を読み、
該当ボタンを自動で押してくれているようですね。

自分で解析して作るしかないかもしれません…。
cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2003-08-01 13:35
うぅ、ちょうど、今、作ってました。

https://www1.bug1ch.net/mscont/applicant.htm

No.14 簡易電卓
cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2003-08-01 13:38
デバッグ中だけど、該当部分のソースも貼っちゃえ。

コード:
protected void Translate(ref string s)
{
	s = Regex.Replace(s,"pi","3.14159265358979");
	TranslateSub(ref s);
}
protected void TranslateSub(ref string s)
{
	string	t;
	string	rep = @"(-?[0-9.]+(?:E[+-][0-9]{1,3}|))";
	for (string pre1 = "" ; ; pre1 = s) 
	{
		for (string pre2 = "" ; ; pre2 = s) 
		{
			for (string pre3 = "" ; ; pre3 = s) 
			{
				for (string pre4 = "" ; ; pre4 = s) 
				{
					t = Regex.Replace(s,@"sin\s*" + rep,new MatchEvaluator(RepSin)); AddList(t,ref s);
					t = Regex.Replace(s,@"cos\s*" + rep,new MatchEvaluator(RepCos)); AddList(t,ref s);
					t = Regex.Replace(s,@"tan\s*" + rep,new MatchEvaluator(RepTan)); AddList(t,ref s);
					t = Regex.Replace(s,@"exp\s*" + rep,new MatchEvaluator(RepExp)); AddList(t,ref s);
					t = Regex.Replace(s,@"log\s*" + rep,new MatchEvaluator(RepLog)); AddList(t,ref s);
					t = Regex.Replace(s,@"sqrt\s*" + rep,new MatchEvaluator(RepSqrt)); AddList(t,ref s);
					if (s == pre4) break;
				}
				t = Regex.Replace(s,@"\(\s*" + rep + @"\s*\)",""); AddList(t,ref s);
				t = Regex.Replace(s,@"\((.*)\)",new MatchEvaluator(RepBrackets)); AddList(t,ref s);
				if (s == pre3) break;
			}
			t = Regex.Replace(s,rep + @"\s*([\*/])\s*" + rep,new MatchEvaluator(RepMulDiv)); AddList(t,ref s);
			if (s == pre2) break;
		}
		t = Regex.Replace(s,rep + @"\s*([\+-])\s*" + rep,new MatchEvaluator(RepPlusMinus)); AddList(t,ref s);
		if (s == pre1) break;
	}
	s = s.Trim();
}

cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2003-08-01 13:44
上のだけだと分からないので。
コード:
string RepBrackets(Match m)
{
	string s = m.Groups[1].Value;
	TranslateSub(ref s);
	return s;
}
string RepMulDiv(Match m)
{
	double	d1 = double.Parse(m.Groups[1].Value);
	double	d2 = double.Parse(m.Groups[3].Value);
	return (m.Groups[2].Value == "*" ? d1*d2 : d1/d2).ToString();
}
string RepPlusMinus(Match m)
{
	double	d1 = double.Parse(m.Groups[1].Value);
	double	d2 = double.Parse(m.Groups[3].Value);
	return (m.Groups[2].Value == "+" ? d1+d2 : d1-d2).ToString();
}
string RepSin(Match m)
{
	return Math.Sin(double.Parse(m.Groups[1].Value)).ToString();
}
private void AddList(string t,ref string s)
{
	if (t == s) return;
	listBox1.Items.Add(s);
	s = t;
}


AddListはデバッグ用に途中の計算状態を出しています。
maru
常連さん
会議室デビュー日: 2001/10/09
投稿数: 23
投稿日時: 2003-08-01 14:51
情報ありがとうございます。
自作するんですね。
今回は横着しちゃおうと思います。
SQLのSELECT文に仕立てて実行してしまおうという手を使おうと思います。
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-08-01 21:33
こんばんは、meiです。

こんなのはどうでしょうか?

コード:
using System;
using MSScriptControl;

// Microsoft Script Controlへの参照が必要
class MyApp {
	static void Main(string[] args) {
		string expr = "1+(2*3)";
		ScriptControlClass sc = new ScriptControlClass();
		sc.Language = "VBScript";

		object result = sc.Eval(expr);
		Console.WriteLine(expr + "=" + result);
	}
}


1

スキルアップ/キャリアアップ(JOB@IT)