- ベストアンサー
pythonのmathモジュールについて
pythonのnumpyモジュールとTkEasyGUIで最小公倍数と最大公約数を求めるコードをGUIの勉強で下記のように書いてみました。最小公倍数と最大公約数の他に公約数の列挙を加えたいと思いmathモジュールのコードに行き着つきました。もともとmathモジュールではarray部分の置換え方が上手く行かなかったのでnumpyで求めるようにしていたのですが、mathに切り替えて使えるようにしたいともいますので方法についてご教授宜しきお願いいたします。 #numpyモジュールとTkEasyGUIで最小公倍数と最大公約数を求める import numpy as np import TkEasyGUI as eg # 画面レイアウトを定義 layout=[ [eg.Label('最小公倍数と最大公約数',color='red',font=("Meiryo",11,'bold'))], [eg.Text("数値を入力してください。",font=("Meiryo",10))], [eg.Input("", key="Input1"),eg.Input("", key="Input2"),eg.Input("", key="Input3"),eg.Input("", key="Input4")], [eg.Button("最小公倍数",background_color="#fff001"),eg.Button("最大公約数"),eg.Button("クリア",pad=(30,5)),eg.Button("キャンセル",background_color="pink")], [eg.Multiline("", key="result",font=("Meiryo",10),size=(40,2))], ] # ウィンドウを表示 with eg.Window("test", layout) as window: for event, values in window.event_iter(): if event == eg.WINDOW_CLOSED or event == "キャンセル": break if event == "最小公倍数" or event == "最大公約数": if values["Input1"] == "" or values["Input2"] == "": array = [0,0] elif values["Input3"] == "" and values["Input4"] == "": array= [int(values["Input1"]),int(values["Input2"])] elif values["Input4"] == "" : array= [int(values["Input1"]),int(values["Input2"]),int(values["Input3"])] else: array = [int(values["Input1"]),int(values["Input2"]),int(values["Input3"]),int(values["Input4"])] if event == "最小公倍数": lcd = np.lcm.reduce(array) window["result"].update(f"最小公倍数は:{lcd}です。") elif event == "最大公約数": max = np.gcd.reduce(array) window["result"].update(f"最大公約数は:{max}です。") if event == "クリア": window["Input1"].update("") window["Input2"].update("") window["Input3"].update("") window["Input4"].update("") window["result"].update("") window.close() #公約数の列挙 def divisors(n): lower_divisors, upper_divisors = [], [] i = 1 while i * i <= n: if n % i == 0: lower_divisors.append(i) if i != n // i: upper_divisors.append(n // i) i += 1 return lower_divisors + upper_divisors[::-1] import math print(divisors(math.gcd(330, 726, 1155, 957)))
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
> 何故mathではなくnumpyにしたか ああ、それはこういう事だろ? >>> import numpy as np >>> import math >>> array = [330, 726, 1155, 957] >>> math.gcd(array) Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> math.gcd(array) >>> np.gcd.reduce(array) 33 う~んとだな。 math.gcdの定義は次のようになっている。 math.gcd: https://docs.python.org/ja/3/library/math.html#math.gcd 要はmath.gcdは可変長引数(好きなだけ引数を取れる)関数なんだけど、それらは裸の整数であってリストではない。 だからエラーになるわけだ。 やりたい事は「リストのカッコを外す」事なんだよな。 それをPythonではアンパックと言う。 引数リストのアンパック: https://docs.python.org/ja/3/tutorial/controlflow.html#tut-unpacking-arguments つまりこう書けばいいんだ。 >>> array = [330, 726, 1155, 957] >>> math.gcd(*array) 33 与えるリスト(array)の前にアスタリスク(*)を付加して書く。そうすれば「カッコがなくなって」math.gcd(330, 726, 1155, 957)と書くのと同じになる、んだ。 ちょっとヘンな、違和感覚える記法だろうけど、こうやってPythonではリストやタプルの「カッコを外す」んだ。 これがPython3.xになってから出来た新しい構文なんだよ。 過去のPython(2.x)時代だと apply(math.gcd, array) とか書かなアカンかったんだけど、随分短く書けるようになって、ラクになった例、かな。 とりあえず、リスト/タプルのカッコを外したい場合は先頭にアスタリスクを付ける、って覚えよう。
その他の回答 (1)
- cametan_42
- ベストアンサー率62% (164/264)
何か、前から回答つかない人だよね。 ちとまずは「回答が付かない理由」から。 そもそも半分以上が「Pythonの質問」じゃないから、なんだよ。 基本的にTkEasyGUIってのが「外部ライブラリ」だから、なんだ。 通常、「外部ライブラリ」に付いてはその「外部ライブラリ」の(あれば)Q&Aフォーラムに投げる、ってのが「正しい」方法なんだ。 何故ならそれらは「Pythonの一般論」じゃなくって、結果、通常、Pythonの公式でも「モヤっとした」回答しか得られなくなる。 しかもTkEasyGUIってのは比較的新しいライブラリだろ?その辺の質問するのなら、作者に投げた方が確実なんだよな。 TkEasyGUIの作者って日本人で(クジラ飛行机氏?多分)、公式サイトで質問受け付けるようなシステム作ってんで、そっちで訊いた方がいいと思う。 Discord > TkEasyGUI: https://kujirahand.com/TkEasyGUI/index.php?Discord&show そもそも、ベースになってるTcl/tk自体が、枯れてて安定してるのはいいんだけど、プログラミングの自由度も少ないし、デザインも正直言うと汚いんで(笑)、そんなにユーザーがいないんじゃねぇのかなぁ。 いずれにせよ、「特定の外部ライブラリに絞った」質問をこういう「一般論」を扱う場所に投げてもあんま回答得られないんだよね。 その辺は覚悟しといた方がいい。 > mathに切り替えて使えるようにしたい いや、gcmとlcmはmathモジュールに含まれてるんで、ドキュメントを参照。 mathモジュール: https://docs.python.org/ja/3/library/math.html > 公約数の列挙を加えたいと思い これはPythonらしく、って前提だとこう書くかな。 def divisors(n): for d in range(1, n + 1): if n % d == 0: yield d これでオシマイ。 色んなトコで「アルゴリズム的には・・・」とか書かれてるけど、Pythonだとジェネレータにしちまった方が素直な解法で、解は短くなる。 yield式: https://docs.python.org/ja/3/reference/expressions.html#yieldexpr # divisorsはジェネレータなんでリスト化する >>> list(divisors(gcd(330, 726, 1155, 957))) [1, 3, 11, 33]
お礼
cametan_42 様 >TkEasyGUIの作者って日本人で(クジラ飛行机氏?多分)、公式サイトで質>問受け付けるようなシステム作ってんで、そっちで訊いた方がいいと思う。 >Discord > TkEasyGUI: 等の情報有り難うございました。 プログラムの知識は雑誌の記事を参考にしている程度の素人なので気になったものについてどんなものか勉強しているだけですので専門のサイトの門をたたくのは気後れしていて、元々使っていたプロバイダのQ&Aサイトのの流れでここで質問している次第です。 何故mathではなくnumpyにしたか array = [int(values["Input1"]),int(values["Input2"]),int(values["Input3"]),int(values["Input4"])] とした場合 math.gcd(array)・・・不成立 np.gcd.reduce(array)・・・成立 但し下記のようにarray = ・・としないで直接代入すれば成立する print(divisors(math.gcd(int(values["Input1"]),int(values["Input2"]),int(values["Input3"]),int(values["Input4"])))) 再度参考サイトをゆっくり読ませていただきます。
お礼
cametan_42 様 早速有り難うございます。 print(math.gcd(*array)) で最大公約数が得られました。アンバック処理をすればいいなんて初めて知りました。いままでのリストとか配列の考え方では気が付きませんでした。 改めてお礼申し上げます。