e-Gadget について

2017/07/31
更新 2020/06/30



e-GadgetCasio Basic をメインテーマにしたブログです。 

カシオの関数電卓にはプログラムを作って実行できるものがありますが、特に日本国内で2006年以降のプログラム関数電卓やグラフ関数電卓の多くに搭載されている Casio Basic の使いこなしが当ブログのメインテーマです。具体的には以下の機種に搭載された Casio Basic を対象にしていて、それ以前の機種のBasic風の言語とは一線を画していることから、私は最近の搭載言語を 新世代 Casio Basic と呼んでいます。

fx-5800P
fx-9860G (fx-9860G AU / fx-9860G SD / fx-9860G Slim)
▶ fx-9860GII (fx-9860GII SD / fx-9860G AU PLUS / fx-9750GII / fx-7400GII)
fx-9750GIII (fx-9860GIII, Graph35+EII) [2020/05/22 追記]
fx-CG20
(fx-CG10)
fx-FD10 Pro
▶ fx-CG50
(Graph90+E)

新世代Casio Basic は、ユーザー関数が作れない、大域(グローバル)変数しか使えないながらも、構造化プログラミング風のコーディングで見通しの良いプログラミングが可能であることは意外に知られていません。このような良さは、昔のポケコンやパソコンで行番号付きBasicプログラミングの経験しかない人、プログラミング経験の少ない人が、チョット触ってみた程度だと分かりにくいと思います。カシオの取扱説明書の記述が簡潔すぎる、言い換えればお粗末な説明しか書かれていないのも、勘違いの大きな原因でしょう。

そこで e-Gadget では、取扱説明書に書かれていない Casio Basic の使いこなし を複数の角度から徹底的に紹介しています。

管理人のPCや周辺機器に関する備忘録や、Windows プログラミングについても少しですが記事にしています。


[2020/06/30 追加]
最近、グラフ関数電卓に Python モードが追加されました。これは、MicroPuthon のサブセット版でカシオ独自のカスタマイズを施したもので、当ブログでは Casio Python と呼んでいます。少し試してみたところ、極めて高速に動作することに驚きました。そこで管理人としては Casio Python を探索しながら、サンプルプログラムの紹介やリファレンスを記事にしています。

現時点では機能不足のため、Casio Basic で作成したプログラムを全て移植できるラベルではなく、極めて物足りないのですが、今後のモジュール追加に期待しつつ、ある程度使いこなせるようにしたいと思っています。

Python モードは、fx-CG50 の OS3.20 から搭載さて、OS3.40 にアップデートしたものが casioplot モジュールが備わり、最も充実しています。一方、新しいモノクロ液晶モデル fx-9750GIIIfx-9860GIII にも Python モードが搭載されていますが、casioplot モジュールは未対応です。そこで、fx-CG50 を前提として Casio Python の記事の連載を始めました。


[2017/08/05 追記]
特定の事柄について当ブログの記事を探す場合は、以下を参考にしてください。

e-Gadget の記事リスト
 ▶ e-Gadget 全体の目次
テーマ別に記事をリストアップしています。元々管理人自身のために作ったもので順不同です。見つけにくいのでスミマセン。いずれ何とかするかも知れません。

Casio Basic の使いこなし
複数のアングルからシリーズ化しています。
 ▶ Casio Basic 入門:じっくりと読みながら実際にプログラムを作って理解を深める
  ∟ Casio Basic (超)入門:fx-5800P で初めてのプログラミング
 ▶ Casio Basic コマンドリファレンス:特定コマンドについて詳しく解説
 ▶ 逆引き Casio Basic:やりたいことからコードを知る
 ▶ プログラムライブラリ:正しく動くプログラムを改造すれば理解が深まる

Casio Basic 使いこなしに隣接するトピックス
Casio Basic、プログラム電卓、その他の管理人が気になるトピックス
 ▶ 楽屋裏

機種別の話題
特定機種をきっかけにして、管理人の好き勝手な方向に掘り下げたトピックス
 ▶ fx-5800P
 ▶ fx-9860GII
 ▶ fx-CG20
 ▶ fx-CG50

カシオ製プログラム電卓の系譜
カシオのプログラム電卓の往年の名機 FX-502Pから最新機種までの代表的なモデルについて、実際にプログラムを作ったり古いカタログを参照しながら、プログラム電卓の系譜を明らかにする
 ▶ プログラム電卓 温故知新
 ▶ プログラム電卓メモワール

アドイン版Casio Basic - 高速・高機能 Casio Basic [2018/08/22 追記]
 ▶ アドイン版 Casio Basic - トップページ

Casio Basic やプログラム電卓以外
Casio Basic や電卓以外のパソコン、通信端末などの管理人のメモに近い話題
 ▶ 番外編



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Pyhton - 目次

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     
- 目 次


初版:2020/06/13
更新:2020/06/30

目 次

リファレンス


連載記事

0. Casio Python のポテンシャル

1. はじめに: 電卓で作る初めてのスクリプト
  1.1 Casio Python での初めてのスクリプト
   1.1.1 fx-CG50 の準備
   1.1.2 Casio Python の起動
   1.1.3 スクリプトファイルの作成
   1.1.4 スクリプトの作成
   1.1.5 スクリプトの実行
  1.2 シェル画面
  1.3 スクリプト作成と編集の2つの方法

2. Casio Python とは?:MicroPython と CPython
  2.1 Casio Python の素性
   2.1.1 MicroPython 1.9.4
   2.1.2 CPython 3.5.4
  2.2 Casio Python に組み込まれているオプジェクト名の一覧
  2.3 Casio Python の学習方法

3. Casio Python の入出力:プログラムのデザイン
  3.1 入力 - input()
  3.2 出力 - print() とグラフィックス出力関数
  3.3 Casio Pyhton で作るプログラム

4. Casio Python への移植:モンテカルロ法(1)
  4.1 コメントの書き方
  4.2 モジュールの呼び出し - import
  4.3 メニュー機能の作成
  4.4 circle() 関数の作成
  4.5 グラフィックス出力
   4.5.1 自作関数 circle() で円を描画
   4.5.2 draw_string() 関数で文字列を出力
   4.5.3 while 文により繰り返し
   4.5.4 random() 関数により正方形内の座標(x, y)を取得
   4.5.5 set_pixel() 関数で (x, y) に点を描画
   4.5.6 点の座標から円周率を計算
   4.5.7 draw_string() 関数で回数と円周率を表示
   4.5.8 draw_string() 関数でシミュレーション終了の表示



リファレンス

Casio Python オプジェクト一覧

作成した個別リファレンスは、オプジェクト一覧からリンクを張ってゆきます。
一旦作成した個別リファレンスは、随時内容を拡充してゆきます。







応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - オブジェクト一覧

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     
- Casio Python オブジェクト一覧


初版:2020/06/28
追加修正:2020/06/30

Casio Python オブジェクト一覧 (fx-CG50 OS3.40)

[SHIFT] [4] (CATALOG) のカタログ機能では表示されない隠しオブジェクトも含んでいます。

個別リファレンスを作成後、リンク張ってゆきます。


データ型
data_type


標準モジュール (builtins)

ステートメント 
構造制御if | elif | else
for | in range() | else | break | continue | pass
while | else | breakcontinue | pass

関数定義
 
def | return | yeild | global | local 

ラムダ関数 (無名関数)
 
lambda

例外処理
 
 
try | exept | else | finally | raise | as | BaseExceptionException | KeyboardInterrupt | StopIteration | SystemExit
 
テスト (デバッグ)
 
assert | AssertionError 
 
モジュール呼び出し
 
import | from | as 
 
クラス定義
 
class | with | as | classmethod()staticmethod() | object 
 
ファイル
 
open (read , write がなく、まだ使えない)
 
数値演算
 
+ | - | * | / | ** | %
 
比較演算
 
< | > | <= | >= | == | != | is | is not | in | not in
 
帰属(所属)検査
 
in | not in
 
ブール演算 (論理演算)
 
and | or | not
 
ビット演算 (論理演算)
 
& | | | ^ | ~ | >> | <<
 
代入
 
=
 
累算代入演算
 
+= | -= | *= | /= | //= | %= | >>= | <<= | &= | ^= | |=
 
三項演算
 
x if 条件式 else y
 
エスケープ
 
\
 
定数
 
True | False | None | Ellipsis 
 
コメント
 
# | ''' | """
 
エラー
 
 
 
 
ArithmetricError | AssertionError | AttributeError | EOFError | GeneratorExit | ImportError | IdentationError | IndexError | KeyError | LookupError | MemoryError | NameError | NotImplementedError | OSError | Overflowerror | RuntimeError | SyntaxError | TypeError | ValueError | ZeroDivisionError 


標準組込関数 (builtins)
出力
 
print()
 
入力
 
input()
 
文の実行
 
eval() | exec() 
 
高階関数
 
map() 
 
シンボルテーブル取得
 
globals() | locals() 
 
クラス/オブジェクト取得
 
 
callable() | dir() | getattr() | hasattr() | hash() | id() | isinstance() | issubclass() | iter() | repr() | setattr()  
 
数値の変換
 
abs() | divmod() | float() | hex() | oct() | pow() | round() | sum() complex() | .imag | .real
 
数値と文字列の変換
 
bool() | chr() | int() | ord() 
 
シーケンス型:
 シーケンス型で共通
 
 
+ | * | all() | any() | .index() | .count() | len() | min() | map() | max() | zip() 
 
 リスト型と辞書型で共通
 
 
*= | .append() | .clear() | .copy() | del.extend() | .insert() | .pop() | .remove() | .reverse()
 
 リスト型
 
[ ] | list() | .sort() | sorted()
 
 タプル型
 
( ) | tuple() 
 
 文字列型とバイナリー
 シーケンス型で共通
 
 
.endswith() | .find() | .isalpha() | .isdigit() | .islowr() | .isspace() | .isupper() | .join() | .lower() | .lstrip() | .replace() | .rfind() | .rindex() | .rsplit() | .rstrip() | .startswith() | .strip() | .upper() 
 
 文字列型
   
' ' | " " | f' ' | f" "str() | eval() | .format() 
 
 バイナリーシーケンス型
 
b' ' | b" " | bytes() | .from_bytes() | .to_bytes() 
 
 range型
 
range() | slice()
 
辞書型

 
 
{ } | dict() | .fromkeys() | .get() | .items() | .keys() | .pop().popitem() | .setdefault() | .update() | .values() | globals() 
 
集合型
print(dir(set)) で取得
 
 

  
{ } | set() | .add() | .clear() | .copy() | .difference() | .difference_update() | .discard() | .intersection() | .intersection_update() | .isdisjoint() | .issubet() | .issuperset() | .pop() | .remove() | .symmetric_defference() | .symmetric_deference_update() | .union() | .update()
 


mathモジュール関数
三角関数
 
acos() | asin() | atan() | atan2(,) | cos() | pi | sin() | tan()
 
指数 / 対数
 
e | exp() | frexp(,) | idexp(,) | log() | log10() | pow() 
 
双曲線関数
 
cosh() | sinh() | tanh() 
 
小数点以下の切上げ / 切捨て
 
ceil() | floor() 
 
絶対値
 
fabs() 
 
剰余計算
 
fmod(,) 
 
整数部と小数部を同時取得
 
modf() 
 
平方根sqrt() 


randomモジュール関数
乱数発生

 
getrandbits() | randrange(,) | randint() | random() | uniform()
 
ランダムに要素を選択
 
choice()
 
乱数ジェネレータ初期化seed()


casioplotモジュール関数
グラフィックス画面消去
 
clear_screen()
 
VRAMへ出力
 
draw_string(,,,) | set_pixel(,,)
 
ピクセル色取得
 
get_pixel(,)
 
VRAMから画面へ転送
 
show_screen()
 







応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - chr()

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - リファレンス 
目次
chr()


初版:2020/06/23

[対応モデル] - fx-CG50 OS3.20 以降、fx-9750GIII / fx-9860GIII OS3.21 以降


0~256までの整数であるアスキーコード(文字コード)に対して、その文字を1文字の文字列として返します。Casio Python はユニコードには対応していません。


Casio Python 独自 - ckChr.py
スクリプト例:
for c in range(30,128):
 
print(str(c)+':'+chr(c))

動作:
アスキーコード 30 から 127 までに対応する文字を出力します。
Casio Python では、アスキーコード32のスペースから、126 の ~ までに文字コードが割り振られています。





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - input()

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - リファレンス 
目次
input()


初版:2020/06/23

[対応モデル] - fx-CG50 OS3.20 以降、fx-9750GIII / fx-9860GIII OS3.21 以降


input() を実行すると入力待ちとなり、[EXE] キーを押すまでの入力を末尾の改行を除いて文字列として返します。
文字列の引数を与えると、文字列の末尾の改行を除いたものをシェル画面に出力してから、入力待ちとなります。


Casio Python 独自
スクリプト例:
prompt='Input numbers and alphabets'
input(prompt)

動作:
Input numbers a~
と16文字以降がに置き換えられて出力し、入力待ちとなります。
入力すると、prompt文字列は
Input numbers and alphabets
と~以降の文字列も出力されます。


Casio Python 独自 - ckAscii.py
スクリプト例:
while 1:
 s=input('Press any key:')
 if len(s)!=1:
  continue
 print(' =>ascii code:'+str(ord(s))+'/'+hex(ord(s))+'\n'))

動作:
電卓のキーを押すと、文字数が1のときにアスキーコードを表示します。
電卓にあるキーには、アスキーコードが割り振られている数字や文字以外に、関数キー、制御キーが多くあります。関数キーは入力すると2文字以上であり、制御キーは0文字なので、1文字ならばアスキーコードを持つ数字や文字だと判定します。そうでなければ continue により while にジャンプして入力処理 input() を実行します。
入力が1文字ならば、アスキーコードを持つ数字や文字なので、ord() でアスキーコードを10進数で出力します。hex() により16進数に変換た文字列を併せて出力します。
無限ループになっているので、終了させるには [AC] キーを押して while ループを抜けます。





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - ord()

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - リファレンス 
目次
ord()


初版:2020/06/23

[対応モデル] - fx-CG50 OS3.20 以降、fx-9750GIII / fx-9860GIII OS3.21 以降


1文字のアスキー文字に対して、その文字のアスキーコードを10進数で返します。Casio Python はユニコードには対応していません。


Casio Python 独自 - ckAscii.py
スクリプト例:
while 1:
 s=input('Press any key:')
 if len(s)!=1:
  continue
 print(' =>ascii code:'+str(ord(s))+'/'+hex(ord(s))+'\n'))

動作:
電卓のキーを押すと、アスキーコード(文字コード)を持つものだけアスキーコードを表示します。
電卓にあるキーには、アスキーコードが割り振られている数字や文字以外に、関数キー、制御キーが多くあります。関数キーは入力すると2文字以上であり、制御キーは0文字なので、1文字ならばアスキーコードを持つ数字や文字だと判定します。そうでなければ continue により while にジャンプして入力処理 input() を実行します。
入力が1文字ならば、アスキーコードを持つ数字や文字なので、ord() でアスキーコードを10進数で出力します。hex() により16進数に変換た文字列を併せて出力します。





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - Casio Python のポテンシャル
目次


初版:2020/06/07
更新:2020/06/29

[2020/06/29 更新]
カシオグラフ関数電卓に Python <パイソン> が搭載されるようになったので、それで遊んでみようと思います。Casio Basic でプログラムを組めるのであれば、Casio Python は意外に敷居が低いかも知れません。

管理人はネットでチョコチョコ調べながら、結構使えています。そこで、 Python 初心者向けに Casio Python のサンプルプログラム作成の連載をしばらくやってみようと思います。先ずは Casio Basic プログラムから Casio Python への移植からスタートし、徐々に Python らしい効率の良いスクリプトへ進んでゆく予定です。併せて、Casio Python のリファレンス情報を公開してゆこうと思います。本連載の全体像は 目 次 をご覧ください。

さて、Casio Python の連載は、管理人がそのポテンシャルの高さに驚いたことが全ての始まりなので、今回はそのあたりを紹介します。
==== 2020/06/29 更新ここまで ====


0. Casio Python のポテンシャル

Python の準備

Casio Python 搭載モデルの準備
Casio Python
搭載電卓を入手して、必要に応じてOSのアップデートをします。

Casio Python が搭載されているのは、以下のモデルです (2020/06/07 現在);
fx-CG50, OS3.20 以降
fx-9750GIII, OS3.21 以降 (北米限定発売モデル)
fx-9860GIII, OS3.21 以降 (ヨーロッパ限定発売モデル)
GRAPH 90+E, OS3.20 以降/ GRAPH 35+EII, OS3.21 以降 (フランス専用モデル)
 それぞれが fx-CG50fx-9860GIII と同じ

なお、グラフィックス用モジュール (casioplot が搭載されるのは下記モデルとOSバージョン以降 (2020/06/07 現在)
 fx-CG50, OS3.40
 GRAPH 90+E, OS3.40
 GRAPH 35+EII, OS3.30

OSバージョンが古い場合は、それぞれのモデルが発売されている地域のカシオサイトからアップデートファイルとアップデートされたマニュアルが入手できます。

我々日本人にとって、国内で入手できて、日本語マニュアルがあるのは fx-CG50 だけなので、今後は OS3.40 以降のOSが搭載された fx-CG50 を前提にします。さらに、OS3.40 より新しいバージョンで新機能や新モジュールが搭載された場合は、随時 対応することにします。

OS3.40 へのアップデートファイルのダウンロード
fx-CG50 (OS3.40) マニュアルのダウンロード


Python スクリプト保存フォルダの作成
工場出荷状態では、ストレージメモリのルートにスクリプトファイルが保存されるようになっています。

これから多くのスクリプトファイルを作ってゆくので、ストレージメモリ直下に専用フォルダ、例えば @Python フォルダを作ると良いと思います。電卓内に新たなフォルダを作るには、PCとリンクしてからエクスプローラで電卓の内部を表示して、そこでフォルダを作ります。


Python スクリプトファイルの正体
スクリプトファイルは、アスキー文字で書かれたテキストファイルです。Python の構造制御に不可欠なインデントは半角スペースです。電卓上でスクリプトを書く場合、自動インデント機能によりスペース2個が付加されます。また、改行は Windows標準の CR LF (0x0d 0x0a)になっています。

PCに転送すれば、テキストエディタを用いて、スクリプトの確認や編集ができます。PCで編集する場合は、アスキーコード以外を入力しないように留意しましょう。



Casio Python とは? [2020/06/09 の夜に大幅改訂]

Casio Python は、ある程度の関数があらかじめビルトインされています(組み込まれています)。それ以外に使いたい関数がある場合は、自分で関数を作って使うことができます。Casio Basic では自分で関数を作って使うことはできませんでしたので、Casio Pythonは使い勝手が良くなっています。

また、あとからモジュールを追加すると、ビルトインされていない関数を新たに使うことができます。Casio Python が公開された最初は、mathモジュールとrandimモジュールが追加された状態でした。その後 casioplotモジュールが追加されて、ようやくグラフィック描画が可能になりました (fx-CG50 OS3.40)。但し、点を打つこと、ドットの色を得ること、テキスト文字を表示することのみができる程度で、Casio Basicのようにグラフを描く機能はまた公開されていません。今後カシオからさらに新しいモジュールが提供されることを期待しています。実は、自分で汎用的に使える便利な関数を作って、モジュールとして使うこともできますが、カシオ提供のモジュールよりは細かな点でどうしても制限がかかってしまいます。

ところで、Casio Basic で書いたものはプログラムと言い、そのファイルをプログラムファイルと言っていました。一方、Python ではスクリプトを書いて、スクリプトファイルに保存する、と言うようです。そこで今後は、スクリプト、スクリプトファイル という言い方にします。

Python は機械学習やDeep Learningのために開発された言語で、1つのことをするには1つの書き方しかないようなポリシーで、分かりやすいことを目指して作られた言語です。さらに様々な専門分野に特化したライブラリ(=モジュール)が様々な人によって多く提供されるようになり、初心者でも専門家でも使いやすい言語して大きな広がりをみせています。また、Webサービスでも使われています。Pythonを使えるようになるのは、時代の先端をゆくようなもので、とても有意義なことだと思います。

念のために言っておきますと、一般に使われている Python に比べて Casio Python は、かなり機能が限定されています。電卓の中だけで使うので、そういうものなのでしょう。しかしながら、初心者の学習や経験者の使いこなしは、一般のPythonよりも、さらに敷居が低いと言えます。

実際に管理人がCasio Pythonを使い始めて感じるのは、提供されている機能が限定されているので、覚えることが極端に少なく、理解が容易だということです。カシオ電卓に搭載されている Python は、組み込み用の Micro Python Ver 1.94 をベースにカシオが電卓用に独自にカスタマイズしたものです。一般のPythonのサブセット版ではありますが、最近のソフトウェア技術のパラダイムに沿った基本仕様は損なわれていませんので、Python の味見用のお試し版、学校での学習用の位置づけではないかと思います。

Casio Basic を使いこなして作ったプログラムを Casio Python に移植しようとすると、機能不足、関数不足のために、どうしても移植できないプログラムがあります。Casio Basic と同じ事を実現するために必要不可欠な機能が Casio Python にはまだ揃っていないのは残念なことですが、それなりに工夫すれば使いこなせると思います。
例えば、Casio BasicGetkeyLocate に相当するものが Casio Python にはありません。
Getkey ⇒ これは、どうにもなりません。カシオさんお願い...
Locate ⇒ さらに機能追加した locate() 関数を自分で作り、なんとか使えています。いずれ紹介しようと思います。

ところで、Python は本来オブジェクト指向言語です。ライブラリ(=モジュール)を呼び出して使う時に、オブジェクト指向特有のobject.method といった記述が必要なケースもありますが、オブジェクトとメソッドをあまり意識しないで、関数型言語のように使える側面もあると思います。特に Casio Python ではほとんど関数型言語のように使っても、とりあえずスクリプトが書けると思います。マニュアルの記述にもオブジェクトやメソッドという単語が殆ど出てこず、関数という表現が多用されています。



Casio Python の潜在能力

純正Casio Basic のプログラムから移植可能なものを 実際にCasio Python書き直してみました。すると、

Casio Basic に比べて実行速度が圧倒的に速い!

以下で紹介しますが、その爆速っぷりは、チョット驚きです!
俄然 Casio Python に興味を持ち、詳細を調べたくなりました。
先ずは、その速さを紹介します。


純正Casio BasicCasio Python の処理速度の比較 
Casio Python でグラフィックス描画、関数計算、加算計算をさせて、純正Casio Basic と比較してみます。

グラフィック描画の比較 - フラクタルでシダの葉

shida_py_s 

これは、以前取り上げたグラクタル図形の描画プログラムです。
fx-CG50 でフラクタル - シダの葉

上で作成した 純正Casio Basic のプログラム SHIDACG.g3m を Python に移植しました。
Casio Basic プログラムファイルと Python スクリプトファイルのダウンロード

フラクタル図形描画時間の比較
純正Casio Basic40 分
Casio Python24.4 秒
アドイン版Casio Basic - C.Basic for CG Ver 1.45β43.0 秒
※ C.Basic for CG Ver 1.45βについては こちらを参照
※ C.Basic は、コードの最適化により、さらに10倍近く高速化可能です。
 比較のため下記の純正Casio Basic コードを走らせました。

Python は100倍速い!

Casio Basicオリジナルコードと Python スクリプトを以下に示します。できる限り忠実に再現していることが分かると思います。

shida_g3m_py_src3


関数計算の比較 - sin と cos の繰り返し計算

tstfinc2_g3m_py_src
TSTFUNC2.g3m と tstfunc2.py のダウンロード

N に1000 を入力した時 (1000回ループ) の関数計算の比較
純正Casio Basic6.5 秒
Casio Python0.6 秒
アドイン版Casio Basic - C.Basic for CG Ver 1.45β0.38 秒

Pythonでの関数計算が10倍速いことが分かります。


加算計算の比較 - 加算とループ

tstsum2_g3m_py_src2  
TSTSIM2.g3m と tstsum2.py のダウンロード

N に1000 を入力した時 (1000回ループ) の加算計算の比較
純正Casio Basic2.2 秒
Casio Python0.15 秒
アドイン版Casio Basic - C.Basic for CG Ver 1.45β0.02 秒

Pythonでの加算計算が15倍程度速い結果になりました。


Python が速い理由
加算計算や関数計算で10~15倍程度速いだけでなく、グラフィックス描画がさらに10倍程度速いことが分かりました。

ちなみに、シダの葉描画のPhytonスクリプトの最下行にある show_screen() を for ループの外に出すと、VRAM上で全てのデータが揃ってから一気に画面転送を行うことになり、この時は 20.8 秒とさらに速くなります。つまり、show_screen() による画面転送速度が極めて速いことが、シダの場描画の爆速の原因と言えます。

複雑な計算やグラフィックスやグラフ表示には極めて役立つという、Casio Pythonの潜在能力が明らかになったと思います。今後のグラフィックおよびグラフ描画のためのモジュール追加が期待されます。

なお、シダの葉描画で利用した clear_screen() メソッドは、マニュアルには載っていません。今後、このような隠し機能の探し方も調べて見たいです。



Casio Python 探索

Casio Python の潜在能力が意外に高いことが分ったので、これから色々と詳細を調べながら探索を進めたいと思っています。

fx-CG50 のマニュアルを読んでも、Python やその他の言語を使ったことがある人しか分からないレベルで、関数やメソッドの使い方は殆ど書かれていません。幸いなことに今ではネットで簡単に調べることができるのではありますが、それでもクラス、メソッドなどで構成される言語に慣れていないと分かりにくいと思います。

そこで、Casio Python を探索しながら、記事をいくつか書こうと思います。



 目 次

次の記事 - 1. はじめに:電卓で作る初めてのスクリプト




応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Pythonへの移植:モンテカルロ法(1)

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - Casio Python への移植:モンテカルロ法(1) 
目次


初版:2020/06/24
表現の修正:2020/06/27
前の記事 - 3. Casio Python の入出力 |  次の記事 - 


4. Casio Python への移植:モンテカルロ法(1)

Casio Basic プログラムを Casio Python へ移植しながら、ざっくりと Python の理解を進めてゆきます。

Casio Python では、入力がシェル画面でしか行えません。そこで、入力はシェル画面で行い、出力はグラフィックス画面で行う方針でスクリプト全体の構造を考え、あとは細かく作ってゆきます。

以下の動作をするスクリプトを作ってゆきます。


このスクリプトは、モンテカルロ法により円周率を求めるシミュレーションです。最初にシミュレーション回数を入力させ、シミュレーション実施の状況をグラフィカルに表示しながら、回数と円周率(pi)の値の変化をリアルタイム表示するものです。


スクリプトの構造

円を描画する関数を定義
 circle() 関数を自作

初期化処理

シェル画面でメニューを表示して、試行回数を入力させる
 print() でメニュー表示
 input() で回数を入力させ整数を取得
 ifによる条件分岐
   テンキー以外を押した時に異常終了しない処理

グラフィックス画面に出力する
 自作関数 circle() で円を描画
 draw_string() 関数で文字列を出力
 whileによる繰り返し(入力した回数分だけ繰り返し)
   random() 関数により正方形内の座標(x, y)を取得
   set_pixel() 関数で正方形内にに点を描画
   点の座標から円周率を計算 (Note 参照)
   draw_string() 関数で回数と円数率を表示
   (ここまでを繰り返す)
 draw_string() 関数でシミュレーション終了の表示


スクリプトの上から下へ制御が流れて行き、if 文while 文 で流れが変化する構造です。

Note:モンテカルロ法による円周率の計算方法
  1. 半径1の円と一辺2の外接正方形を考えます。
  2. x=1-2×[0~1の乱数]、y=1-2×[0~1の乱数] を計算して、-1<x<1-1<y<1 の (x, y)を得ます。
    つまり、(x, y) は一辺2の正方形内のランダムな点の座標となります。
  3. 正方形内にランダムに円を打って行き、全ての点の数を outs とし、そのうち x2+y2<1 になる(円内になる)回数を ins とします。(オリジナルのCasio Basic プログラムでこういう感じなので、単純に移植するために追従します)
  4. [正方形の面積]:[円の面積]outs:ins=4:π なのて、π=4×outs/ins となります。

円描画関数の作成
Casio Python には、円を描画する組み込み関数が無いので、自分で作る必要があります。
ここでは、円の中心位置を決める x 座標と y 座標、そして円の半径 r をパラメータに指定すると円を描画する関数を作ります。
Python の書式に従って、
 def circle(x, y, r):
  必要な処理

と記述します。詳細は 4.4 circle() 関数の作成 で説明します。

初期化処理
各変数の初期値を設定します。個別の処理と一緒に説明します。

シェル画面でメニュー表示と入力
主に、print() 関数と input() 関数の使いこなしがポイントです。if 文も使います、詳しくは 4.3 メニュー機能の作成 で説明します。

グラフィックス画面に出力
set_pixel() 関数と draw_string() 関数、そして clear_screen() 関数と show_screen() 関数の使いこなしがポイントです。 while 文も誓います。詳しくは 4.5 グラフィックス出力 で説明します。 



今回作るスクリプトは、"これだけ知っていれば、ほぼ何でも作れる最低限の Casio Python の知識" で作りました。今回のメインテーマは、そのレベルの知識を紹介することです。

今回紹介する内容について、ネットで詳しく調べたり、より Python らしいコードを習得すれば、学習が深まると思います。


4.1 コメントの書き方

Pythonスクリプトでコメントを書くには、# を使うか トリプルクォート を使います。

Python公式:Comments
PEP 8 - Style Guide ofr Python の Comments の項 に推奨するコメントのスタイルが書かれています。ここでは、# を使ったブロックコメントとシングルラインコメントの推奨スタイル、そして3重ダブルクォーテーションを使った docstrings の推奨スタイルについて書いてあります。

Note:PEP 8
Python 公式文書 では、開発者のためのガイドラインや開発した機能が Python Enhancment Proposals (PEPs) にまとめられています。そして、全ての PEP はインデックス番号で文書管理されていて、コメントに関する推奨スタイルは PEP 8 にまとめられています。

#
# から行末までが、コメントとして扱われ、実行されません。公式推奨スタイルでは、# のあとにスペース1個を置いてからコメントを書くことになっています。また、説明を入れる記述と同じインデントレベルで書くことを推奨しています。
Casio Python は画面が狭いので、管理人は #  の後のスペースを入れないことが多いです。

Key Press:#
エディタ画面(スクリプト編集画面) で、[F3] (SYMBOL) - [F6] (▷) と押すと、[F1] (#) で # を入力できます。


''' (トリプルクォート - 3重シングルクォーテーション)
'''''' の間がコメントとして扱われます。複数行をまとめてコメントにすることができます。

Key Press:'
エディタ画面で、[F3] (SYMBOL) - [F6] (▷) と押すと、[F2] (') で ' を入力できます。


""" (トリプルクォート - 3重ダブルクォーテーション)
"""""" の間がコメントといsて扱われます。複数行をまとめてコメントにすることができます。
Python のスタイルガイドでは、公開する関数やメソッドに関する説明は、3重ダブルクォーテーションを使った Documentation Strings を推奨しています。

Keypress:"
エディタ画面で、[F3] (SYMBOL) - [F6] (▷) と押すと、[F3] (") で " を入力できます。

Python公式:Domumentation Strings (Docstrings)
PEP 8 - Style Guide for Python の Documentation Strings の項 に詳しく書かれています。
・def 文の行の下の行を """ で始め、これに続いてその関数の説明をできるだけ簡潔に1行以内で書きます。
・そして、空行を入れます。
・空行の下から、パラメータや戻り値の説明を入れます。

Casio Python では、"""""" の間はピンク色になって分かりやすくなります。度 (degree) で表した確度をラジアン (radian) に変換する関数での Docstrings の一例です(たった2行のスクリプトなので、コメントばかりで大げさになっています);

 def rad(x):
 
"""Returns angle in radian

 Parameters:

 ーーーーーーーーーーーーー
 x: float
  angle in degree

 Returns:

 ーーーーーーーーー
 float
  angle in radian
 """

 return pix/180


4.2 モジュールの呼び出し - import

Python は、最初から組み込まれている builtins モジュールに加えて、後からモジュールを追加して使える機能を増やせるようになっています。Casio Python は、math モジュールと random モジュールが追加された状態で最初にリリースされ、その後 casioplot モジュールが追加されました。今回は、これら全てを使いますので、モジュールの呼び出しをスクリプトの冒頭に書く必要があります。

例えば、set_pixel() 関数を使いたい場合は、それが含まれている casioplot モジュールを呼び出します。関数を使う前に、モジュールの呼び出しを記述しなければなりません。呼び出し方法は2通りあり、それによって関数の使い方が変わります。


import モジュール名

書 式
import casioplot
casioplot.set_pixel(x, y)

モジュールに含まれる関数を使う際は、関数の前に モジュール名. を追加しなければなりません。
casioplot オブジェクトに帰属する関数は、. で繋いで明示的に帰属関係を示す必要があります。これはオブジェクト指向言語に共通する書式と言えます。


from モジュール名 import *

書 式
from casioplot import
set_pixel(x, y)

はワイルドカードで、casioplot から全ての関数を呼び出すという意味で、帰属関数の関数名だけを書いて使えるようになります。

 これまでをまとめたスクリプト:
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *



4.3 メニュー機能の作成

シミュレーション試行回数を変数 temp_try に入れることにします。試行回数 (try数) の仮変数という意味で temp を使って、temp_try という変数名にしました。

そこで、入力処理で最低限必要な記述は、

temp_try = input()

となります。

これを実行するとシェル画面で入力待ちになりますが、何も表示されず入力を待っています。そしてテンキーで数値を入力してから[EXE]キーを押すと、変数 temp_try に数値が格納されます。但し、input() の戻り値は、数値ではなくて文字列になるのが仕様で、これに留意します。

さて、次のようにすれば、入力の際に分かりやすくなります;
temp_try = input('Input number:')


Reference:⇒ input()

Note:Python での文字列 - ' ' と " "
string = '12345abcd'
あるいは
string = "12345abcd"
と書けば 変数 string は文字列型の変数として自動的に定義され、srting に文字列データ格納されますす。
Python では、シングルクォーテーションでもダブルクォーテーションでも、どちらでも使えます。
例えば、文字列の一部に " が入っている時、文字列の定義で ' を使えば " が文字列の一部として使える、といったメリットがあります。
string = 'He said "Wow"'
print(string)
を実行すると、
He said "Wow"
と出力されます。

Python で文字列は、シングルクォーテーション ' あるいは ダブルクォーテーション " で挟みます。Python 公式文書ではシングルクォーテションを使う事例が普通に使われているので、ここでは ' を使うことにします。そこで、文字列をパラメータに指定して input('Input number') と書きます。

これを実行すると、シェル画面では以下のようになります;

Input number:

そして、Input number: の直後でカーソルが点滅しているので、入力が分かりやすくなります。

monteca_input_1 

これで十分ですが、管理人は余計な表示を消したくなります。それだけでなく、このプログラムの説明も表示したくなります。

シェル画面では、[EXE}キーを押して改行すると、表示が上へスクロールされます。シェル画面の表示をクリアする関数が用意されていないので、余計な表示は改行でスクロールするしかありません。

そこで、print() 関数を使って表示を追加してみます。

以下のような表示を目標にします。
monteca_first_screen 

プログラム開始時は、試行回数500回をデフォルトにしておき、[EXE]キーでスグにシミュレーション開始。回数を変えたい場合は入力してから[EXE]キーを押してシミュレーション開始、となる仕様にします。これは、print() 関数と input() 関数だけで実現できます。

print(文字列) とするとシェル画面に文字列が表示され、改行されるのが、デフォルトの仕様です。
文字列なしで、単に print() とすると、文字列はシェル画面に表示されずに、改行だけが行われます。

すると、上の表示を行ってから最後に入力待ちにするには、以下のようにします。
・改行のみ
・Monte Carlo: calc Pi と表示して海魚う
・改行のみ
・# of try:500 と表示して改行
・[EXE} to start. と表示して改行
・改行のみ
・input() で Change the #? と表示して入力待ちして、変数 n に格納

これをスクリプトで書くと、文字列は ' ' の間に書くので、以下のようになります。
print()
print('Monte Carlo: calc Pi')
print()
print('# of try:500')
print('[EXE] to start.')
print()
temp_try = input('Change the #?')


ところで、エスケープシーケンスの1つである '\n' を文字列に使って print('\n') を実行しても改行されます。\ はバックスラッシュといい、/ (スラッシュ) とは傾きが違っていることに注意してください。

Key Press:\ (バックスラッシュ)
エディタ画面で、[F4] (CHAR) を押して、キャラクタ一覧から \ を選びます

そこで、上のスクリプトを書き換えてみます。

print('/nMonte Carlo: calc Pi')
print('/n# of try:500')
print('[EXE] to start.')
temp_try = input('/nChange the #?')


さて、ここで変数 temp_try に代入されるのは文字列です(input() の仕様)。例えば 1000 とキー入力すると temp_try には 文字列 '1000' が格納されます。ここでは、シミュレーション回数の変数 n_try に数値として 1000 を代入したいところです。
そこで、関数 int() を使います。

Note:int()
int(x) は、浮動小数点あるいは文字列の x を整数に変換します。浮動小数点については、小数点以下を切り捨てて整数にします。文字列については、数字だけの文字列なら整数に変換し、数字以外の文字列が含まれるときはエラーになります。

n_try = int(temp_try) とすると、n_try に整数が格納されます。

temp_try が数字だけの文字列かどうかを判定するには、isdigital() 関数が使えます。これは文字列オブジェクトの帰属関数なので、文字列型オプジェクト名に . を使って繋げて記述します。ここでは、文字列型のオブジェクトである temp_try の帰属関数として使うので、temp_try.isdigit() と書きます。

n_try = 500
if temp_try.isdigit():
 n_try = int(temp_try)


こうすると、デフォルトの試行回数が500回で、正しく数値が入力されたときは、その整数値を n_try に代入し、数値以外の文字が含まれた時は、n_try にはデフォルトの500回が適用された状態で、次の処理に進みます。

Note:if 文
if 文の書式
 if
条件1:
  処理1
  ・・・
 elif 条件2:
  処理2
  ・・・
 else:
  処理3
  ・・・
条件1が True (真)のとき(成り立つ時)あるいは 0 でない時、処理1を実行、
条件2が True (真)のとき(成り立つ時)あるいは 0 でない時、処理2を実行
それ以外のとき、処理3を実行
ifelifelse の行末にはコロン : が必要です。
コロン : の次の行には、インデントを1段深くします。深くなったインデントレベルが同じ行が if の範囲を示します。
elif でインデントレベルが1段戻り、if と同じインデントレベルにします。これにより ifelif が同列だと示します。
elif の行末にもコロン : が必要で、その下の行のインデントレベルで elif の範囲を示します。
else: の範囲も同様です。
このように、インデントレベルはスクリプトの正しい実行のために、極めて重要です。


Note:Python のデータ型
Casio Python で使う頻度の高いデータ型は、ざっくりと 数値型とシーケンス型に分けられ、それぞれいくつかのデータ型に分けられます。
数値型: 整数型浮動小数点型があります。
シーケンス型文字列型リスト型タプル型辞書型
 シーケンス型は、複数要素を並べたデータ型です。
 そして要素のデータ型の種類に応じて、以下のデータ型があります。
数値型変数の定義:   val = 123
浮動小数点型変数の定義:val = 12.34
文字列型変数の定義:val = '12.34'
リスト型変数の定義:val = [12, 16, 24, 48]  val=['I', 'have', 'a', 'pen', '.']
タプル型変数の定義:val = (255,255,0)
辞書型変数の定義: val = {'ketchup':'red', 'mustard':'yellow', 'coffee':'black'}
   要素を囲む記号で、シーケンス型に属する細かいデータ型が決まります。

今回は、整数型、浮動小数点型、文字列型の3つのデータ型を使います。


 これまでをまとめたスクリプト:
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *

#initializing
n_try 500

#display menu to select try#
print('\nMonte Carlo: calc Pi')
print('\n# of try:'+str(n_try))  #ココの説明がまだでした!
print('[EXE] to start.')
temp_try input('\nChange the #?:')
if temp_try.isdigit():
 n_try int(temp_try)

まだ説明していなかった点を補足します。

上の作りかけのスクリプトでは
 print('\n# of try:') 

 print('\n# of try:'+str(n_try))
に変更しています。

数値変数 n_try を文字列に変換したものを + (文字列結合)を使って、文字列 '\n# of try:' に結合しています。
数値を文字列に変換するために、str() 関数を使っています。

Note:str()
str(x) は、オブジェクト x を文字列に変換して返します。x に整数型や浮動小数点型を指定すれば、文字列型で返します。


これで、以下の表示と動作の目標を達成しました。
monteca_10000_start 


4.4 circle() 関数の作成

これから、円を描画する circle() 関数を作ります。

この関数の書式を以下のようにします。
 circle(x, y, r)
 x: 整数型 (int型)、円中心の x 座標
 y: 整数型 (int型)、円中心の y 座標
 r: 整数型 (int型)、円の半径


関数を定義するには、def 文を使います。

 def circle(x,y,r):
  処理1
  処理2
   :
   :


def 文の行末には、コロン : が必要です。
コロン : の下の行は、インデントレベルを1段深くします。同じインデントレベルの行が、def の範囲を決めます。

circuit() 関数を使う場合は、例えば、circle(100,100,50)circle(px, py, r) のように書きます。3つのパラメータは、第1引数は x 座標値、第2引数は y 座標値、第3引数は 半径、といったように引数の順序、つまりその位置で意味が決まります。これを位置引数 (Positional Argument) と言います。

circle() 関数の定義は、circle() を使う前に記述する必要があります。スクリプトは家から下へ実行されるからです。今回は、スクリプトの冒頭、モジュール呼び出しの下に記述することにします。

 circle_desc 
circle() 関数で、左上の座標が (0, 0) 、右へ正の x 軸、下へ正の y 軸のグラフィックス画面(描画画面)で、中心座標が (x, y)、半径 r の円を描画します。

円を p 個の点で描画する時、描画する点(上で赤い点) 順次  i を 0 から p-1 まで1づつ変化させながら、角度 i*a で描画します。
ここで、円を描く際の角度の1刻みが 角度 a になります。

以下のような方法で円を描画することにします;

def circle(x, y, r):
 p = (式)
 a = (式)
 for i in range(p):
  px = x + r*cos(i*a)
  py = y + r*sin(i*a)  
  draw_pixel(int(px), int(py))
  show_screen()


==========

この方針に従って、実際にスクリプトを仕上げます。

Casio Python での三角関数は、角度がラジアンに限定されていますので、スクリプトはラジアンで書く必要があります。そこで、1週が 2π ラジアンなので、p 個の点で円を描画するときの角度の1刻み a は、2π を p で割った角度になります。
 a = 2*pi/p
で、a を算出します。

ところで、math モジュールには 円周率を返す関数として pi があります。そこで、math モジュールを呼び出した上で、上のように pi を使います。

すると、上の図から分かるように、i 番目の点の座標 (px, py) は次のように計算できます。
 px = x + r*cos(i*a)
 py = y + r*sin(i*a)

 
座標 (px, py) に点を描画するには、
 set_pixel(px, py)
を使いますが、px と py は整数でないとダメです。液晶パネルのドットは整数の座標で決まります。
しかし、上で計算した px と py は浮動小数点になっています。そこで、int() 関数を使って、浮動小数点の小数を切り捨てて、整数に変換します。

 set_pixel(int(px), int(py))

とすればOK。

そして、set_pixel() 関数でVRAMにデータ転送したものを、show_screen() 関数で画面に転送すれば、点が表示されます。

==========

この点の描画を、i を 0 から p-1 (整数) まで1づつ変化させながら繰り返すには、for 文を使います。

for i in range(p):
 px = x+r*cos(i*a)
 py = y+r*sin(i*a)
 set_pixel(int(px), int(py))

 show_screen()

set_pixel() 関数は、VRAMにデータを書き込むだけで、画面への転送を行いません。そこで、show_screen() 関数で画面にデータ転送を行うことで、描画が完了します。

Note:for 文
for i in range(p):
 処理

は、整数 ip-1 になるまで1つづつ増やしながら、処理を繰り返します。
for 文の行末にはコロン : が必要です。コロン : の下の行はインデントレベルを1段深くします。このインデントレベルが同じ行がfor の範囲、つまり繰り返し処理の対象になります。ここでも、コロン : とインデントレベルは、正常動作のために極めて重要です。

==========

最後に、円を描画するために使う点の数 p の値を決めます。

円の描画は、できる限りきれいで滑らかにしたいので、p は十分に大きくすれば良いのでしょうが、一方、できる限り短い時間で効率よく処理するには、p は必要最小限にしたいところです。この条件に合う点の数 p をどうやって決めるのかを考えてみます。適当で良いのかも知れませんが、チョットこだわってみます。

円を描画するとき、点と次の点の間隔が一番大きくなるのは、画面横幅 387 の半径の円がx軸と垂直に交わる時です(必要条件)。その時に点と点の間隔の y座標の変化が1ピクセルになるときの点の数を Pmax とします。Pmax は、半径が 383 (画面横幅)の円を描画する時の点の数です。383 よりも小さな半径 r の円を描くための点の数 p は、Pmax よりは少なく

p = Pmax × (r/383)   (式1)

で十分だと分かります (Pmax を半径 383r で比例配分したもの)。

半径 383 の円で y座標値が一番急激に変化するのは、角度 0 の時なので、y座標値が 1 (pixel) だけ変化するときの角度変化を θ とすると、この θ は、滑らかに円を描画するために無駄のない最大の角度刻みとなります。これ以下の角度刻みは無駄だし、これ以上だと歯抜けの円となります。

この角度刻み θ は、383×sin(θ) = 1 となるときの θ です。この式を変形すれば、θ は以下のように計算できます。

θ = sin-1(1/Pmax) = sin-1(1/383)

半径 383 で、さらに角度刻み θ で点を描画して円にするとき、1週するのに必要な点の数、つまり Pmax は以下になります。

Pmax = 2π/θ = 2π/sin-1(1/383) ≃ 2406  (式2)

(式1) と (式2) から、以下の式で p が決まります。この p は、半径 r の円を描画するときに、滑らかでかつ無駄のない最小の描画点数です。

p = r*2406/383 = r*6.28198

==========

以上まとめると、中心座標が (x, y)、半径が r の円を描画する関数は、以下になります。

def circle(x, y, r):
 p = r*2406/383
 a = 2*pi/p
 for i in range(p):
  px = x+r*cos(i*a)
  py = y+r*sin(i*a)
  set_pixel(int(px), int(py))
  show_screen()


さて、描画しようとする点 (pxpy) がグラフィックス画面の外側の時は、描画しないて次へ進んだ方が、さらに処理時間が節約できて、より効率化できます。

そこで、px を求める計算の直後に、px<0 または px>383 の時は、set_pixel() をスキップして、次の繰り返しを実行するようにします。それには、以下の赤の2行を追加します。

  px = x+r*cos(i*a)
  if px<0 or px>383:
   continue


同様にして、py を求める計算の直後に、py<0 または py>191 の時は、set_pixel() をスキップして、次の繰り返しを実行するように、以下の赤の2行も追加します。

  py = y+r*sin(i*a)
  if py<0 or py>191:
   continue



Note:continue
繰り返し処理(ループ)を行う for 文 と while 文 で、繰り返し処理の中で continue を使うと、それ以降の処理を行わずに forwhile にジャンプできます。

Reference:⇒ range()

これで circle() 関数ができました。


 これまでをまとめたスクリプト:
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *

#draw circle
def circle(xyr):
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r
sin*(i*a)
  if py<0 or py>191:
   continue 
  set_pixel(int(px)int(py))
  show_screen()

#initializing
n_try=500

#display menu to select try#
print('\nMonte Carlo: calc Pi')
print('\n# of try:'+str(n_try))
print('[EXE] to start.')
temp_try input('\nChange the #?:')
if temp_try.isdigit():
 n_try int(temp_try)

#display graphics
#これ以降を書いて、プログラムを完成させます


4.5 グラフィックス出力

Casio Python でグラフィックス画面 (描画画面) へ出力する関数は、点を描画する関数 set_pixel() と 文字列を描画する draw_string() の2つしかないので、これらを使いこなしたいと思います。set_pixel() については既に説明したので、ここでは、draw_string() に焦点を当てます。

これらのグラフィックス出力関数は、VRAMへのデータ転送を行い、画面への出力までは実行しません。従ってフラフィックス画面への出力は、show_screen() 関数を実行する必要があります。

[SHIF] [4] (CATALOG) で表示されるカタログ機能に含まれないのですが、グラフィックス画面を消去する clear_screen() 関数があります。隠し関数です。

Note:Casio Python 組み込み関数を調べる
既に紹介しているように、隠し関数を調べるために ObjName.py が使えます。
これで見つかるのはオブジェクト名なので、ネットで詳細を調べる必要があります。


モンテカルロ法シミュレーションプログラムのグラフィックス画面への出力ブロックは、冒頭で書いたように、以下の手順でスクリプトを書いてゆきます。

 =============================================
 4.5.1 自作関数 circle() で円を描画
 4.5.2 draw_string()
関数で文字列を出力
 4.5.3 while
文による繰り返し(入力した回数分だけ繰り返し)
 4.5.4  random()
関数により正方形内の座標(x, y)を取得
 4.5.5  set_pixel()
関数で正方形内に点を描画
 4.5.6  
点の座標から円周率を計算
 4.5.7  draw_string()
関数で回数と円数率を表示
      
(ここまでを繰り返す)
 4.5.8 draw_string()
関数でシミュレーション終了の表示
 =============================================

4.5.1 自作関数 circle() で円を描画

円の中心座標を (290, 96) とし、半径を 90 とするので、以下を記述すればOKです。
そこで、それぞれを以下の変数に代入したものを使います。(数値を直接使っても問題ありませんが、あとで変更する可能性を考えて、初期化処理のブロックで変数宣言して、それを使うことにします。

以下を 初期化処理のブロックに追加します。
 r = 90 #radius
 dx = 290dy = 96 #center


Note:文の句切り文字 - ;
Python では、文の句切りとして改行が使われます。1行に複数の文を記述したいときは、文の句切り文字としてセミコロン ; も使えます。

円を描画するために、コメント #display graphics の下に
 circle(dx, dy, r)
を追記します。


4.5.2 draw_string() 関数で文字列を出力

以下のような出力になるようにスクリプトを書きます。
monteca_graphics_2 

 #initializing
 n_try 500
 r 90 #radius
 dx 290dy 96
#center


 #display graphics
 clear_screen()
 circle(dx,dy,r)
 draw_string(12,0'C=')
 draw_string(0,16'pi=')
 draw_string(0,160'# of try:'+str(n_try))
 draw_string(0,176'AC:Quit')
 show_screen()

今回既に説明した内容で書けると思います。


4.5.3 while 文による繰り返し

Python
には、繰り返し処理 (ループ) を行うために for 文と while 文の2つしかありません。for 文は既に使ってみました。ここでは While 文を使います。

Note:while 文
while 条件:
 処理1
 処理2

これが、while文の書式で、while の行末にはコロン : が必要で、コロンの行の下のインデントレベルを1段深くします。同じインデントレベルの行が、while による繰り返し処理の対象になります。

今回の繰り返し条件については、あとで説明します。


4.5.4 random() 関数により正方形内の座標(x, y)を取得

乱数発生関数 random() を使います。random() は、0 以上 1 未満のランダムの数値を返します。
ここでは、x が -1 ~ +1、y が -1 ~ 1 の間の乱数を取得します。

 x=1-2*random()
 y=1-2*random()



4.5.5 set_pixel() 関数で (x, y) に点を描画

点を描画するのは、円の中心 (dx, dy) と同じ座標を中心として1辺が2の正方形の範囲内です。そこで、点を描画する座標は、
 (dx+r*x, dy+r*y) 
となります。但し、set_pixel() のパラメータは、整数でないとエラーになるので、それぞれ int() で小数点以下を切り捨てて整数にします。

さらに、点を描画するには、set_pixel() を実行後に show_screen() を実行します。

 set_pixel(int(dx+r*x), int(dy+r*y))
 show_screen()



4.5.6 点の座標から円周率を計算

Note:モンテカルロ法による円周率の計算方法 (再掲)
  1. 半径1の円と一辺2の外接正方形を考えます。
  2. x=1-2×[0~1の乱数]、y=1-2×[0~1の乱数] を計算して、-1<x<1-1<y<1 の (x, y)を得ます。
    つまり、(x, y) は一辺2の正方形内のランダムな点の座標となります。
  3. 正方形内にランダムに円を打って行き、全ての点の数を outs とし、そのうち x2+y2<1 になる(円内になる)回数を ins とします。(オリジナルのCasio Basic プログラムでこういう感じなので、単純に移植するために追従します)
  4. [正方形の面積]:[円の面積]outs:ins=4:π なのて、π=4×outs/ins となります。
これをスクリプトで表現します。

 if x**2+y**2<1:
  ins+=1
 outs+=1
 pai = round(4*ins/outs, 11)


さて、While の条件を保留にしていましたが、ここで決めます。点を1つ描画するために 変数 outs が1づつ増えます。そこで、outs が試行回数 n_try よりも小さいこと、つまり outs<n_try を繰り返しの条件とします。

Note:累乗演算子 - **
x2Python では、x**2 と書きます。

Note:累算代入演算 (+=, -=, +=, /=, %=)
ここで、+= という演算があります。C言語系の経験があれば、おなじみだと思いますが、累算代入演算と言います。
ins+=1 は、ins=ins+1 と同じで、これを省略して記述するための演算子です。
a = a+b は、a+=b
a = a-b は、a-=b
a = a*b は、a*=b
a = a/b は、a/=b
a = a%b は、a%=b
と書けます。
一方、C言語系でおなじみに ++ 演算子(インクリメント、1増やす) を使って ins++ とすると、Pythonではエラーになります。

Note:四捨五入 - round()
Casio Python の浮動小数点は、小数点以下の有効桁数は15です。
シェル画面で、
 from math import *
 pi
を実行すると円周率が表示されますが、小数点以下15桁になっています。
今回のプログラムでは、計算結果の円周率は、何もしないと小数点以下15桁で表示されます。この桁数だと点描画の領域にテキストが上書きされます。これを避けるために、round() 関数を使って、
 pai = round(4*ins/outs, 11)
により、小数点以下11桁を指定して四捨五入しています。


4.5.7 draw_string() 関数で回数と円周率を表示

draw_string(36, 0, outs)
draw_string(36, 16, pai)


とすれば良いはずです。


ここまでをまとめます。

 これまでをまとめたスクリプト:
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *

#draw circle
def circle(x,y,r):
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r*sin(i*a)
  if py<0 or py>191:
   continue
  set_pixel(int(px)int(py))
  show_screen()

#initializing
n_try 500
ins = 0; outs = 0
90 #radius
dx 290dy 96 #center

#display menu to select try#
print('\nMonte Carlo: calc Pi')
print('\n# of try:'+str(n_try))
print('[EXE] to start.')
temp_try input('\nChange the #?:')
if temp_try.isdigit():
 n_try int(temp_try)

#display graphics
clear_screen()
circle(dx, dy, r)
draw_string(12,0'C=')
draw_string(0,16'pi=')
draw_string(0,160'# of try:'+str(n_try))
draw_string(0,176'AC:Quit')
show_screen()

while outs<n_try:
 x 1-2*random()
 y 1-2*random()
 set_pixel(int(dx+r*x), int(dy+r*y))
 if x**2+y**2<1:
  ins+=1
 outs+=1
 pai round(4*ins/outs,11)
 draw_string(36,0str(outs))
 draw_string(36,16, str(pai))
 show_screen()


さて、下から3行部分について、見てみます。実は、これではテキスト表示が次々と上書きされ、真っ黒になってしまいます。
そこで、数字をカウントアップして、次々と変化が見えるようなスクリプトを検討します。


カウントアップのスクリプト

先ず、以下のスクリプトを作って検討します;

from casioplot import *
c = 0
clear_screen()
while c<=1000:
 draw_string(0, 0, str(c
))

 show_screen()
 c+=
1


変数 c を while ループを回るたびに 1 づつカウントアップし、それをグラフィックス画面に表示しています。
下から3行目 は、次々と上書きするので、以下のようになります。
countup_1 

そこで、同じところに空白文字で上書きすることで消去したのち、c の値を出力すれば良いというのは、いつも行うことです。
 draw_string(0, 0, '   ')
 draw_string(0, 0, s)


これでは、解決しません。スペースは空白文字ではないことが分かります。
では、明示的にスペースのエスケープシーケンス \x20 (16進数) あるいは /32 (10進数) を使ってみます。
 draw_String(0, 0, '\x20\x20\x20\x20')
 draw_srting(0, 0, s)


これでもダメです。
ちなみに、スクリプト編集画面で、[F4] (CHAR) を押してキャラクタセットを見てみると、そこには空白文字が見当たりません。スペースあるいは空白文字で上書きする方法は、Python では有効ではなさそうです。ネットで調べてみても、それらしい解決方法が簡単には見つかりません。

draw_string() 関数の第3パラメータ(引数) で、文字色を設定できます。そこで、同じ文字列を背景色の白で描画すれば、消去できるはずです。ループで前回描画したときのカウント cprev_c 変数に代入しておき、次に prev_c を白で描画すれば、目的の動作が可能になりそうです。そこで、次のようにスクリプトを変更してみます。

from casioplot import *
c = 0
clear_screen()
while c<=1000:
 draw_string(0, 0, str(prev_c), (255,255,255)) #追加
 draw_string(0, 0, str(c
))

 show_screen()
 prev_c = c #追加
 c+=
1


文字色の指定は、RGB指定なので、(255,255,255) で白を指定します。
これで目的が達成できました!!

ところで、追加した draw_string(0, 0, prev_s, (255,255,255)) の次に show_scree() も追加してみると、数値表示がチカチカして見づらくなります。show_screen() で画面への転送を行うと、消去した文字列が一旦表示されるのが原因です。そこで、VRAM上で、文字列消去と次の文字列データの書き込みを行ったのち、一気に画面への転送を行うのが良いわけです。


これと同じ方法を、モンテカルロ法のスクリプトに適用します。ループの1回前にの outs と pai の値を prev_outs と pre_pai の2つの変数に一旦格納します。そして、次のループでの文字列表示の前に、前回の文字列を白色で出力します。

 これまでをまとめたスクリプト:
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *

#draw circle
def circle(x,y,r):
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r*sin(i*a)
  if py<0 or py>191:
   continue
  set_pixel(int(px)int(py))
  show_screen()

#initializing
n_try 500
ins = 0; outs = 0
prev_outs = 0
prev_pai = 0
90 #radius
dx 290dy 96 #center

#display menu to select try#
print('\nMonte Carlo: calc Pi')
print('\n# of try:'+str(n_try))
print('[EXE] to start.')
temp_try input('\nChange the #?:')
if temp_try.isdigit():
 n_try int(temp_try)

#display graphics
clear_screen()
circle(dx, dy, r)
draw_string(12,0'C=')
draw_string(0,16'pi=')
draw_string(0,160'# of try:'+str(n_try))
draw_string(0,176'AC:Quit')
show_screen()

while outs<n_try:
 x 1-2*random()
 y 1-2*random()
 set_pixel(int(dx+r*x), int(dy+r*y))
 if x**2+y**2<1:
  ins+=1
 outs+=1
 pai round(4*ins/outs,11)
 draw_string(36, 0, str(prev_outs), (255,255,255))
 draw_string(36, 16, str(prev_pai), (255,255,255))
 draw_string(36,0str(outs))
 draw_string(36,16, str(pai))
 show_screen()
 prev_outs = outs
 prev_pai =
pai


4.5.8 draw_string() 関数でシミュレーション終了の表示

シミュレーションが終了したときは、以下のように、左下の表示を Finish=>[EXIT] に変更しようと思います。
monteca_500 

シミュレーション実行中は、左下に AC:Quit と表示されています。そこで、これを白色で出力したのち、Finish=>[EXIT] を黒で出力すれば良いことは既に分かっています。

draw_string(0, 176, 'AC:Quit', (255,255,255))
draw_string(0, 176, 'Finish->[EXIT]')
show_screen()



このスクリプトは、while ループの外で実行するので、インデントレベルは while の中の処理よりも1段浅くしなければなりません。

 完成したスクリプト: monteca1.py のダウンロード
"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"

by Krtyski/e-Gadget
"""

from casioplot import *
from random import *
from math import *

#draw circle
def circle(x,y,r):
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r*sin(i*a)
  if py<0 or py>191:
   continue
  set_pixel(int(px)int(py))
  show_screen()

#initializing
n_try 500
ins = 0; outs = 0
prev_outs = 0
prev_pai = 0
90 #radius
dx 290dy 96 #center

#display menu to select try#
print('\nMonte Carlo: calc Pi')
print('\n# of try:'+str(n_try))
print('[EXE] to start.')
temp_try input('\nChange the #?:')
if temp_try.isdigit():
 n_try int(temp_try)

#display graphics
clear_screen()
circle(dx, dy, r)
draw_string(12,0'C=')
draw_string(0,16'pi=')
draw_string(0,160'# of try:'+str(n_try))
draw_string(0,176'AC:Quit')
show_screen()

while outs<n_try:
 x 1-2*random()
 y 1-2*random()
 set_pixel(int(dx+r*x), int(dy+r*y))
 if x**2+y**2<1:
  ins+=1
 outs+=1
 pai round(4*ins/outs,11)
 draw_string(36, 0, str(prev_outs), (255,255,255))
 draw_string(36, 16, str(prev_pai), (255,255,255))
 draw_string(36,0str(outs))
 draw_string(36,16, str(pai))
 show_screen()
 prev_outs = outs
 prev_pai =
pai

draw_string(0, 176, 'AC:Quit', (255,255,255))
draw_string(0, 176, 'Finish->[EXIT]')
show_screen
()


4.6 まとめ

Casio Python でスクリプトを書くための最低限の知識をざっくりと説明しました。
入出力に必要な関数、構造制御構文である 条件分岐 (if)、繰り返し処理(for, while) について、今回のスクリプトでおおよその使い方が分かったのではないかと思います。

各関数やメソッドについて詳しく知りたい場合は、ネットで確認してください。なお、Casio Python特有の仕様と思われるものは、別途 Reference として取り上げました。



目 次

前の記事 - 3. Casio Python の入出力

次の記事 - 





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - range()

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - リファレンス 
目次
range()


初版:2020/06/23

スクリプト例
p = 2.1
print(p)
for count in range(p)
 print(count)

動 作
シェルへ 浮動小数点型の pprint(p) で出力し、その後 for 文により countprint(count) で出力を複数回実行します。

2.1
0
1
2

p
が整数でなく浮動小数点であるのにエラーにならず、p の値を切り上げた整数値として range() が動作します。


これは、Casio Python の仕様だと思われます。
本来 CPython ではエラーになるコードですが、MicroPython のサイトでは CPython との違いとして公開されていません。Casio Python 独自拡張の可能性が高いと思います。








応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Python - 入出力

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - Casio Python の入出力:プログラムのデザイン 
目次


初版:2020/06/20
前の記事 - 2. Casio Python とは? |  次の記事 - 4. Casio Python への移植


3. Casio Python の入出力:プログラムのデザイン

Casio Python の標準入出力はシェル画面です。それに加えて、グラフィックス画面が出力先として使えます。


3.1 入力 - input()

Casio Python で入力を行うのは、input() 関数のみです。
これだけ覚えておけば、入力処理が可能です。

input() 関数で取得できるのは数値と文字列のみです。input() 関数が実行されると、入力待ちとなり、キー入力を行った後[EXE]キーを押して入力確定となり、処理が次に進みます。

Note: Casio Python の制限
input() による数値や文字列の取得以外に、電卓にある多くキーが押されたことを取得するのは、今のところ Casio Python ではできないと思います。例えば、プログラムが動作中にキー入力により処理を変更することはできません。リアルタイムのキー入力を可能にする機能追加が大いに待たれます。


3.2 出力 - print() と グラフィックス出力関数

Casio Python で可能な出力先は、シェルへの出力とグラフィックス画面(描画画面)です。
マニュアルでは描画画面と書かれていますが、ここではグラフィックス画面と言うことにします。

シェル画面への出力は、print() 関数のみです。

グラフィックス画面への出力は、あとで追加された casioplot モジュールで提供される set_pixel()draw_string()show_screen()、そして隠し関数である clear_screen() が使えます。これらの関数については、詳しい説明がマニュアルに記載されています。Casio Python では、グラフィックス出力を優先的に考えているように思われます。

Note: シェル画面とグラフィックス画面の切り替え
画面にデータを出力するとき、先ずVRAMメモリに出力データを書き込み、次にそれを画面に転送します。

print() 
関数は、VRAMへの書き込みとシェル画面への転送をまとめて実行します。
グラフィックス関数 set_pixel()draw_srting() はVRAMへの書き込みだけを実行し、VRAMからグラフィックス画面へ転送するには、show_screen() を実行する必要があります。

グラフィックス画面に切り替えるには show_screen() を実行し、シェル画面に切り替えるには print() (パラメータ無し) を実行します。これらの画面切り替えを行うための 電卓のハードウェアキーは、割り当てられていません (OS3.40)。


3.3 Casio Python で作るプログラム

シェル画面でしか入力ができないのは、プログラムを作る上で大きな制約になります。そこで、プログラム実行の条件をシェル画面で入力させ、その後グラフィックス画面に切り替えて、テキストやグラフィックスの出力を行うのが良いと思います。

この方針で、以前 Casio Basic で作ったモンテカルロ法による円周率計算のプログラムを、Casio Python に移植してみました。
オリジナルの Casio Basic プログラムについては、fx-9860GII モンテカルロ法 をご覧下さい。


Monte Carlo Method by Python ver 1.0: monteca1.py のダウンロード

入力と出力を切り替える方法で以下のように Casio Python に移植しました。

起動直後は、シェル画面でシミュレーション回数を指定するようにしました。デフォルトで500回です。ここで、10000 と入力して、[EXE]キーを押します。
monteca_first_screen monteca_10000_start 

すると、グラフィックス画面への出力に移行します。
monteca_500 monteca_3193 

500回、3193回と、点が増えてゆきます。

monteca_7639 monteca_10000 

実際の動作をみると、Casio Python の処理速度が高いことがよく分かります。





Casio Basic のコードを Casio Python に移植しながら、Casio Python について調べた結果を、次回はざっくりと紹介しようと思います。



目 次

前の記事 - 2. Casio Python とは?

次の記事 - 4. Casio Python への移植





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

最新記事
検索フォーム
最新コメント
カテゴリ
C# (3)
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

実際に触って気づいたこと、自作プログラム、電卓プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではなく、Casio Basicが面白いと感じる1ユーザーです。


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR