ども、機械です。
欲しかった簡単な統計機能を組み込んで、一応完成です。
今回は、普及版で教科書もあるPython1.5.2対応版も書きましたが、
現在、私がPython1.5.2環境が無いので、もし使っておられる方が
いましたら、テスト/デバッグお願いいたします。
まぁ、電卓としてはこんなトコでしょう。
これ以上となれば、データのセーブ/ロード機能やグラフ描画機能等
ということになるでしょうし、実際、可能だと思いますが、少し時間を
置いてみたいと思います。
GUIのサンプルとしては、ボタンやメニューといった定番でなく、
キャンバス描画やキー入力といった、どっちかというと往来のDOS
的なイベントを扱ってますので、ゲームなんか作る人には参考になる
んじゃないかしらん、と思います。
--^ rpn_v100.py
"""
逆ポーランド式計算機 ver.1.00
Python 2.2以降
<仕様>
+-*/ 四則演算
Enter スタックプッシュ
Delete 入力行クリア
BS 入力行1文字削除
Home 内部スタック及び入力行全クリア
End 計算機プログラム終了
↑ 入力行とスタックトップの交換(swap)
← 整数切り捨て
→ 小数点2位
↓ 16進法表示(値は捨てられる)
L 常用対数(log10)
P power(べき乗)
S 合計・平均・標準偏差表示
R 平方根
<用語>
TOS : Top of Stack(スタックの一番上のデータのこと)
<履歴>
1.00 簡易統計機能を組み込んで、ようやく完成版
"""
tempValue = 0
posX = 450
posY = 50
numchar="0123456789abcdefxABCDEFX."
stackLine = 4
BG = "Yes" # 背景表示をするなら"Yes"
# 背景画はXBM形式のモノクロでファイル名はbg.xbm
# 大きさは480x360以内
class CalcData: # 保存内部データの殆ど
"""Class of calculate data"""
def __init__(self):
self.stack = []
self.inputStr = ""
self.tempValue = 0
self.newLine = 0
# スタック関連のメソッド
def push(self,str=None): # スタックプッシュ
if str==None:
if self.inputStr == "":
self.stack.append("0")
else:
self.stack.append(self.entryLineDisplay())
else:
self.stack.append(str)
return self
def pop(self): # スタックポップ
if self.stack.__len__():
return self.stack.pop()
else:
return "0"
def len(self): # スタックの長さ取得
return self.stack.__len__()
def __getitem__(self,key): # スタックアイテムの参照
return self.stack[key]
def __setitem__(self,key,value): # スタックアイテムの代入
self.stack[key] = value
def swap(self): # 入力行とTOSの入れ替え(内部処理)
if self.len():
self[-1] , self.inputStr = self.inputStr , self[-1]
def total(self): # スタック内の合計値を返す
t = 0
for x in self.stack:
t += float(x)
return t
def ave(self): # スタックの平均値Average
t = self.total()
l = self.len()
if l == 0:
return 0
else:
return t/l
def std(self): # スタックの標準偏差 Standard Diviation
l = self.len()
if l == 0:
return 0
else:
ave = self.ave()
s = 0
for x in self.stack:
s += abs(float(x) - ave)
s = s/l
return s
def clearStack(self): # 全スタッククリア(内部処理)
self.stack = []
return self
def str(self,txt=None): # 入力行整形用メソッド
if txt==None:
return self.inputStr
else:
self.inputStr = txt
return self
def flag(self,n=None): # 入力行取り扱い指示フラグ
if n == None:
return self.newLine
else:
self.newLine = n
def str_empty(self): # 入力行の内容の有無を取得
if self.str() == "" or self.str() =="0":
return 1
else:
return 0
def backDelete(self): # 一文字削除(内部処理)
if self.inputStr:
self.inputStr = self.inputStr[:-1]
def clearLine(self): # 入力行削除(内部処理)
self.inputStr = ""
return self
def addChar(self,c): # 一文字追加(内部処理)
self.inputStr = self.inputStr + c
return self
def entryLineDisplay(self): # 入力行表示指示
if self.str() == "":
return "0"
else:
return cd.str()
cd = CalcData() # 計算データインスタンス作成
import Tkinter as tk
import sys,math
class DisplayView:
"""Calculator Display Class"""
def showBG(self): # 背景画表示
self.canvas.create_bitmap(
0,0,anchor=tk.NW,
bitmap="@bg.xbm",foreground="gray"
)
def setText(self,txt,x,y): # 文字表示
self.canvas.create_text(
x,y,text=txt,
fill = "green",
anchor = tk.NE,
font = "Helvetica 15 bold"
)
def alert(self,txt): # 警告表示
self.canvas.create_text(
10,10,text=txt,
fill = "red",
anchor = tk.NW,
font = "Helvetica 15 bold"
)
def show(self): # 画面書き換えメソッド
self.canvas.delete(tk.ALL)
if BG == "Yes":
self.showBG() # 背景表示
sc = stackLine
while sc:
pY = posY * (5 - sc)
if cd.len() >= sc:
self.setText(cd[-sc],posX,pY)
else:
self.setText("0.0",posX,pY)
sc -= 1
self.canvas.create_line(
10,230,470,230,fill="green"
)
self.setText(
cd.entryLineDisplay(),
posX,
(posY * 5)
)
def allClear(self,event): # 全スタッククリア
cd.clearStack().clearLine()
self.show()
def enterValue(self,event): # 入力数プッシュ
cd.push()
cd.flag(2)
self.show()
def calc(self,opr): # 演算メソッド
if cd.str_empty() and opr=="/":
self.alert("ZERO DIVIDE!")
else: # 行が長いので、2行に(笑)
e = "tempValue=0.0+" + cd.pop() + opr
e = e + cd.entryLineDisplay()
exec e
cd.str(str(tempValue))
cd.flag(1)
self.show()
def backSpace(self,event): # 一文字削除
cd.backDelete()
self.show()
def deleteKey(self,event): # 入力行削除
cd.clearLine()
self.show()
def swap(self,event): # 入力用とTOSの入れ替え
cd.swap()
cd.flag(1)
self.show()
def math_ex(self,action):# 数学拡張
cd.str(
str(
action(
float(
cd.entryLineDisplay()
)
)
)
)
cd.flag(1)
self.show()
def math_ex2(self,action):# 数学拡張(2項)
cd.str(
str(
action(
float(
cd.pop()
),
float(
cd.entryLineDisplay()
)
)
)
)
cd.flag(1)
self.show()
def format_ex(self,format): # 書式変換(本体)
cd.str(
str(
format % float(
cd.entryLineDisplay()
)
)
)
cd.flag(1)
self.show()
# 特殊キーによる書式変換メソッド(ラッパー)
def intform(self,event):
self.format_ex("%i")
def f2form(self,event):
self.format_ex("%.2f")
def hexform(self,event):
self.format_ex("%x")
cd.clearLine()
# 数値や四則・論理演算子の処理
# フラグが0なら、直接入力続行
# フラグが1で入力行が空行でないなら、自動プッシュ
# フラグが2なら、入力行を削除
def inputCharacter(self,event):
if event.char in numchar:
if cd.flag():
if cd.flag()==1:
if not cd.str_empty():
cd.push()
elif cd.flag() == 3: # 統計用特殊表示クリア
cd.clearStack()
cd.clearLine()
cd.flag(0)
cd.addChar(event.char)
self.show()
elif event.char in "+-*/":
self.calc(event.char)
elif event.char=="l":
self.mathex(math.log10)
elif event.char=="r":
self.mathex(math.sqrt)
elif event.char=="p":
self.mathex2(pow)
elif event.char=="s":
self.stat()
else:
self.alert("BAD KEY!")
def stat(self): # 統計処理Statistic
cd.push()
t = cd.total()
a = cd.ave()
s = cd.std()
cd.clearStack().clearLine()
cd.flag(3)
cd.push("Total = " + str(t))
cd.push("Average = " + str(a))
cd.push("Standard Diviation = " + str(s))
self.show()
cd.flag(3)
def __init__(self,master): # キー割り当て
self.canvas = tk.Canvas(
master,width = 480,height=360,bg="black"
)
self.canvas.bind("<Home>",self.allClear)
self.canvas.bind("<Return>",self.enterValue)
self.canvas.bind("<BackSpace>",self.backSpace)
self.canvas.bind("<Delete>",self.deleteKey)
self.canvas.bind("<Up>",self.swap)
self.canvas.bind("<Left>",self.intform)
self.canvas.bind("<Right>",self.f2form)
self.canvas.bind("<Down>",self.hexform)
self.canvas.bind("<Key>",self.inputCharacter)
self.canvas.bind("<End>",sys.exit)
self.canvas.pack()
self.show()
self.canvas.focus_set()
# プログラム開始
root = tk.Tk()
dv = DisplayView(root)
root.title("RPN Calculator ver.1.00")
root.mainloop()
--$
--^ rpn_v101.py
"""
rpn_v101.py
逆ポーランド式計算機 ver.1.01
Python 1.5.2以降対応版
<仕様>
+-*/ 四則演算
Enter スタックプッシュ
Delete 入力行クリア
BS 入力行1文字削除
Home 内部スタック及び入力行全クリア
End 計算機プログラム終了
↑ 入力行とスタックトップの交換(swap)
← 整数切り捨て
→ 小数点2位
↓ 16進法表示(値は捨てられる)
L 常用対数(log10)
P power(べき乗)
R 平方根
S 簡易統計機能:合計・平均・標準偏差表示
<用語>
TOS : Top of Stack(スタックの一番上のデータのこと)
<履歴>
1.00 簡易統計機能を組み込んで、ようやく完成版
1.01 普及版のPython 1.5.2に対応できるよう、
一部記述を変更
"""
tempValue = 0
posX = 450
posY = 50
numchar="0123456789abcdefxABCDEFX."
stackLine = 4
BG = "Yes" # 背景表示をするなら"Yes"
# 背景画はXBM形式のモノクロでファイル名はbg.xbm
# 大きさは480x360以内
class CalcData: # 保存内部データの殆ど
"""Class of calculate data"""
def __init__(self):
self.stack = []
self.inputStr = ""
self.tempValue = 0
self.newLine = 0
# スタック関連のメソッド
def push(self,str=None): # スタックプッシュ
if str==None:
if self.inputStr == "":
self.stack.append("0")
else:
self.stack.append(self.entryLineDisplay())
else:
self.stack.append(str)
return self
def pop(self): # スタックポップ
if len(self.stack):
k = self.stack[-1]
self.stack = self.stack[:-1]
return k
else:
return "0"
def len(self): # スタックの長さ取得
return len(self.stack)
def __getitem__(self,key): # スタックアイテムの参照
return self.stack[key]
def __setitem__(self,key,value): # スタックアイテムの代入
self.stack[key] = value
def swap(self): # 入力行とTOSの入れ替え(内部処理)
if self.len():
self[-1] , self.inputStr = self.inputStr , self[-1]
def total(self): # スタック内の合計値を返す
t = 0
for x in self.stack:
t = t + float(x)
return t
def ave(self): # スタックの平均値Average
t = self.total()
l = self.len()
if l == 0:
return 0
else:
return t/l
def std(self): # スタックの標準偏差 Standard Diviation
l = self.len()
if l == 0:
return 0
else:
ave = self.ave()
s = 0
for x in self.stack:
s = s + abs(float(x) - ave)
s = s / l
return s
def clearStack(self): # 全スタッククリア(内部処理)
self.stack = []
return self
def str(self,txt=None): # 入力行整形用メソッド
if txt==None:
return self.inputStr
else:
self.inputStr = txt
return self
def flag(self,n=None): # 入力行取り扱い指示フラグ
if n == None:
return self.newLine
else:
self.newLine = n
def str_empty(self): # 入力行の内容の有無を取得
if self.str() == "" or self.str() =="0":
return 1
else:
return 0
def backDelete(self): # 一文字削除(内部処理)
if self.inputStr:
self.inputStr = self.inputStr[:-1]
def clearLine(self): # 入力行削除(内部処理)
self.inputStr = ""
return self
def addChar(self,c): # 一文字追加(内部処理)
self.inputStr = self.inputStr + c
return self
def entryLineDisplay(self): # 入力行表示指示
if self.str() == "":
return "0"
else:
return cd.str()
cd = CalcData() # 計算データインスタンス作成
import Tkinter
tk = Tkinter
import sys,math
class DisplayView:
"""Calculator Display Class"""
def showBG(self): # 背景画表示
self.canvas.create_bitmap(
0,0,anchor=tk.NW,
bitmap="@bg.xbm",foreground="gray"
)
def setText(self,txt,x,y): # 文字表示
self.canvas.create_text(
x,y,text=txt,
fill = "green",
anchor = tk.NE,
font = "Helvetica 15 bold"
)
def alert(self,txt): # 警告表示
self.canvas.create_text(
10,10,text=txt,
fill = "red",
anchor = tk.NW,
font = "Helvetica 15 bold"
)
def show(self): # 画面書き換えメソッド
self.canvas.delete(tk.ALL)
if BG == "Yes":
self.showBG() # 背景表示
sc = stackLine
while sc:
pY = posY * (5 - sc)
if cd.len() >= sc:
self.setText(cd[-sc],posX,pY)
else:
self.setText("0.0",posX,pY)
sc = sc - 1
self.canvas.create_line(
10,230,470,230,fill="green"
)
self.setText(
cd.entryLineDisplay(),
posX,
(posY * 5)
)
def allClear(self,event): # 全スタッククリア
cd.clearStack().clearLine()
self.show()
def enterValue(self,event): # 入力数プッシュ
cd.push()
cd.flag(2)
self.show()
def calc(self,opr): # 演算メソッド
if cd.str_empty() and opr=="/":
self.alert("ZERO DIVIDE!")
else: # 行が長いので、2行に(笑)
e = "tempValue=0.0+" + cd.pop() + opr
e = e + cd.entryLineDisplay()
exec e
cd.str(str(tempValue))
cd.flag(1)
self.show()
def backSpace(self,event): # 一文字削除
cd.backDelete()
self.show()
def deleteKey(self,event): # 入力行削除
cd.clearLine()
self.show()
def swap(self,event): # 入力用とTOSの入れ替え
cd.swap()
cd.flag(1)
self.show()
def math_ex(self,action):# 数学拡張
cd.str(
str(
action(
float(
cd.entryLineDisplay()
)
)
)
)
cd.flag(1)
self.show()
def math_ex2(self,action):# 数学拡張(2項)
cd.str(
str(
action(
float(
cd.pop()
),
float(
cd.entryLineDisplay()
)
)
)
)
cd.flag(1)
self.show()
def format_ex(self,format): # 書式変換(本体)
cd.str(
str(
format % float(
cd.entryLineDisplay()
)
)
)
cd.flag(1)
self.show()
# 特殊キーによる書式変換メソッド(ラッパー)
def intform(self,event):
self.format_ex("%i")
def f2form(self,event):
self.format_ex("%.2f")
def hexform(self,event):
self.format_ex("%x")
cd.clearLine()
# 数値や四則・論理演算子の処理
# フラグが0なら、直接入力続行
# フラグが1で入力行が空行でないなら、自動プッシュ
# フラグが2なら、入力行を削除
def inputCharacter(self,event):
if event.char in numchar:
if cd.flag():
if cd.flag()==1:
if not cd.str_empty():
cd.push()
elif cd.flag() == 3: # 統計用特殊表示クリア
cd.clearStack()
cd.clearLine()
cd.flag(0)
cd.addChar(event.char)
self.show()
elif event.char in "+-*/":
self.calc(event.char)
elif event.char=="l":
self.mathex(math.log10)
elif event.char=="r":
self.mathex(math.sqrt)
elif event.char=="p":
self.mathex2(pow)
elif event.char=="s":
self.stat()
else:
self.alert("BAD KEY!")
def stat(self): # 統計処理Statistic
cd.push()
t = cd.total()
a = cd.ave()
s = cd.std()
cd.clearStack().clearLine()
cd.flag(3)
cd.push("Total = " + str(t))
cd.push("Average = " + str(a))
cd.push("Standard Diviation = " + str(s))
self.show()
cd.flag(3)
def __init__(self,master): # キー割り当て
self.canvas = tk.Canvas(
master,width = 480,height=360,bg="black"
)
self.canvas.bind("<Home>",self.allClear)
self.canvas.bind("<Return>",self.enterValue)
self.canvas.bind("<BackSpace>",self.backSpace)
self.canvas.bind("<Delete>",self.deleteKey)
self.canvas.bind("<Up>",self.swap)
self.canvas.bind("<Left>",self.intform)
self.canvas.bind("<Right>",self.f2form)
self.canvas.bind("<Down>",self.hexform)
self.canvas.bind("<Key>",self.inputCharacter)
self.canvas.bind("<End>",sys.exit)
self.canvas.pack()
self.show()
self.canvas.focus_set()
# プログラム開始
root = tk.Tk()
dv = DisplayView(root)
root.title("RPN Calculator ver.1.01")
root.mainloop()
--$
以上のスクリプトは、転載・改造その他自由ですので、勝手に使って
遊んでみてください。
機械伯爵