2024年12月28日土曜日

芝村先生のCASIO関数電卓インタビューが出ていた

 X のポストに、以下の記事へのリンクを示すものがあったので、見てみましたヨ。とっても嬉しい内容。

ref. 【現場の電卓】僕がExcelでなく関数電卓を手にする理由~「刀剣乱舞」のゲームデザイナー・芝村裕吏さんにききました
https://www.casio.co.jp/topics/article/2024/K-071/

驚いちゃったなァ。芝村先生、CASIOグラフ電卓使いだったとは。
こうした記事が年末に出て、やはり、2025年のCASIO は、関数電卓方面で何かやってくれそうな、そんな予感がいたします。

一方で、fx-FD10 が「生産完了品」になっていたのは、チョット残念。


2024年11月26日火曜日

fx-CG50 の X post が増えていたので

 fx-CG50 の X post がやたらと増えていたのですが、殆どが、以下の記事を引用したものでした。

ref. 第1回 Python電卓を使ってみよう Pythonが動くリアル電卓「fx-CG50」
https://news.mynavi.jp/techplus/article/calcpython-1/

大手web媒体の連載で、読み応えもありそうですが ... 残念な事に、メール登録しないと読めない。「一見さん、お断り」なのネ。どうせ広告なんだから、吝い事を言いなさんな。

そんな"広告"の中でも、以下のpostは、やす親分の引用でしたネ。シロン ( @_Chiron__ ) 様、多謝であります !

ref. https://x.com/_Chiron__/status/1860534381561151816

で、CG50の後継機種と目されている、fx-CG100の話は、日本では全く聞かれないのでありますが、最近、妙な事を考えておりまして。
fx-CG100では、Add-Ons や CASIO BASIC などが、対応しなくなりそうという事らしい。ストレージも削減されているとかで、どちらかと言うとfx-CG100より「後退」していそうな印象。

他方で、(Sentaro様曰く、CASIOが追っかけている ?) TI の電卓では、upython 対応が徐々に進められていて、最近では、micro:bit を接続して使用する、などの機能が提供されていると。
この micro:bit 接続機能ですが、TIの電卓では以前から、センサーキットやRoverキットなどの接続機能があって、そうしたハードウェア拡張の一環、という位置付けらしい。

実は、fx-CG50でも、センサーキットと接続して、センサー入力したデータを分析するアプリケーションが用意されておりました。センサーキット自体が入手困難な上、手頃ではなさそうなのですが、この辺りは、TIの電卓を追いかけていた様で、まさに、Sentaro様の言う通りであります。
ちなみに、データ分析アプリでは、FFTなどの機能があったりします。結構実用的な感じですが、データを取得し、分析する機能がアプリ側で閉じられているので、外部からデータを放り込んで分析をする、という芸当が出来ない辺り、ショボーンな訳ですネ。
尤も、FFTを使う、という事であれば、XCASに機能があるので、Add-OnsでXCASを使えば、勉強になるんじゃろか ?

で、TI電卓 の micro:bit 接続機能なんかでも、micro:bit に接続したセンサーなどのデータを読み込むみたいな作業が出来るとかで、そうして取得したデータをグラフ表示する、という作例が、以下で紹介されておりました。

ref. TI-Python と micro:bit の連携について
https://qiita.com/inachi/items/8306c73a9ed76e72b28e

原理的には、fx-CG50でもできそうな気がするのですが、目下の所、fx-CG50 の upython 機能は、イマイチ足りない。
fx-CG100辺りでは、upythonの機能を拡充するらしい、という観測もあって、例えばUSB port 経由で通信機能などを充実する事で、micro:bit 接続機能に類似した事が可能になってくれると、TI の追っかけ風で、チョット面白いかなぁ、などと不埒な事を妄想してしまったのであります、ハイ。

2025年、「CASIOがきっと、何かやる」事を期待しつつ。

2024年11月16日土曜日

「fx-CG50 でもやってみた」チャレンジ ?

 先日、つぎの post を見かけました。

https://x.com/RR_Inyo/status/1853820210874376698

実機が手元にないのでオンラインシミュレータですが,0になりました!
NumWorksは根号などをある程度そのまま扱うようです。

(sqrt(2)-1)^10 - (3363-2378*sqrt(2)) = 0
Numworks の話題でしたが、それでは、我らが fx-CG50 ではどうなのかと試した所、残念ながら fx-CG50 では、累乗の計算について、整式での計算は行いませんでした。

「くやしいのう、くやしいのう」

しかし、諦めが悪いので、どうにかして、同様の計算結果が得られないモンか、と、考えてみましたヨ。

この整式の計算自体は、2項定理の計算を行えば出来そうです。
(sqrt(2)-1)^n の計算でありますから、sqrt(2) の累乗部分を、うまく括りだすことが出来れば、当初の目的は達する筈であります。

そこで、2項定理の計算で用いる「組み合わせ」の機能をもつ BASIC で、かんたんなプログラムを作成しました。

```
For 0->N To 20

0->A
0->B

For 0->K To N
If MOD(N-K,2)=1
Then
N nCr K*2^((N-K-1)/2)*(-1)^K+A->A
Else
N nCr K*2^((N-K)/2)*(-1)^K+B->B
IfEnd

Next

A->List 11[N+1]
B->List 12[N+1]

Next
```
これを実行すると、20次までの累乗について、List11, List 12 に、係数の数列が保存されます。
この数列は、(sqrt(n)-1)^n = A*sqrt(2) + B と展開した場合、
List 11 ; A
List 12 ; B
が保存されます。

例えば、(sqrt(n)-1)^10 = -2378*sqrt(2) + 3363 でしたが、
List 11[11] = -2378
List 12[11] = 3363
となる寸法。(残念ながら、リストの添字は1始まりなので、10乗の場合には、添字11に保存される具合)

ここまで苦労したものの、fx-CG50 には XCAS が作られております。これを使えば「答えイッパーツ !」でしたね。

(sqrt(2)-1)^10 と入力し、simplify() を適用する事で、所望の結果が得られましたヨ。さすがは XCAS。

で、延々作業したものの、n->inf の極限では、(sqrt(2)-1) < 1 なので (sqrt(2)-1)^inf -> 0 に収束するという、泣けてくるオチまで用意して、このネタを終わりにしたいと思います。

2024年10月11日金曜日

10000回のループを使って、ちょっとした作業

 fx-CG50 の upython の実行速度に甘えて、ちょっとした作業をやってみました。
数列 1/k の総和を求める作業です。

sum(1/k, k, 1, 10000) という表記をしてみましたが、upython で書けば、こんな作業です。

sum = 0
for k in range(1, 10001) :
   sum = 1/k

1/k 自体が、無限大で 0 に収束するので、「総和も 0 に収束して紅か ?」と考えるのですが、実際には、無限大まで加算すると、発散してしまうのですね。

取り敢えず、10000まで累積総和を計算させてみます。
10000以上にすると、結果はさらに増えていくのですが、この計算、加算の数を多くすると、それにつれて累積数が増えていくのです。
それを「視覚的に」納得しようと。さて、どうするか ?

「手始めに、1から10000までの区間で、グラフを描いたらよかろう !」

グラフ電卓なので、簡単操作でグラフを描いてくれそうですが、実際には、チョット面倒な事になりました。「級数の総和を求める」というのは「関数」で書けません。

そこで、upython のパワーでグラフを描いてみることにしました。
しかし、やってみると解りますが、どうもこの級数和、収束するのかしないのか、はっきりした感じでは掴めません。

そこで「飛び道具」的な手段を導入しましました。対数目盛りのグラフです。
グラフ電卓ですから、対数目盛りのグラフなんかも簡単に描けそうなものですが、実際には、そういった手段が提供されておりません。

そこで、簡単に横軸対数目盛りのグラフを描く、upython スクリプトを用意しました。
このスクリプトを読み込ませると、じわじわと累積して、点を打っていきます。
ループ上限が10000にしてあり、横軸のみを対数目盛りにして、累積数の点を打っておきます (縦横の軸までは描きません) 。

描かれたグラフをみるとわかりますが、それまでは「どこかで伸び悩みそうな累積数のグラフ」が、横軸を対数目盛りにすると、直線になっているのが解ります。
直線ですから、この先、いくらでも増えていくのは想像に難くありません。

こうして、視覚的に納得する事ができました。流行り(?)の「納得と共感」です。

今回も upython の計算速度を利用した「力技」な話題となりました。
こうしたちょっとした計算が手のひらの上で愉しめます。

数学的には、奥深い話題が展開できそうなのですが、その辺りは目下、お勉強の最中なので、機会がありましたらいずれまた、としておきます。

【スクリプト】

from casioplot import *
import math

wi=382
he=191
xs=1
xe=10000
ys=0
ye=10

sum=0
for i in range(xs,xe+1) :
  sum+=1/i
  ii=(math.log10(i)-math.log10(xs))/(math.log10(xe)-math.log10(xs))*wi
  jj=(ye-sum)/(ye-ys)*he
  set_pixel(int(ii),int(jj))
  show_screen()


2024年10月4日金曜日

自家製 copysign() の顛末

 過日、Biomorph for fx-CG50 の記事で、自家製 cmath module を開陳致しました所、K 様から、コメントを頂戴致しました。

K 様の方法で cmath.sqrt() を書くと、計算がスムースに行く上、境界部分での符号の扱いも良い具合になるのですが、残念な事に、fx-CG50 には math.copysign() がなく、適用な手段で代替関数を用意する必要があると、K 様も申されておりました。

そこで、copysign() 風の関数を自作すれば、よかんべ、と調べ始めたのですが、copysign() では、符号チュエックのため、0.0 と -0.0 という値に対応するという話でありますネ。ナニソレ ?

浮動小数点数も符号が用意されているのは解っていたつもりですが、折角だから、0.0 にも符号を付けて、0.0 と -0.0 の2つを用意しよう、という話らしい。
処理系 (コンパイラ) が、ゼロ符号に対応した場合に、python もこれに対応できるらしく、最近のモダンな処理系では、-0.0 という浮動小数点数に対応されている様です。

そんな具合で、我らが fx-CG50 の upython も、-0.0 という数値自体は扱える様に出来ております。
シェルを呼び出して、-0.0 と入力すると、そのもの -0.0 が答えとして返ってきますネ。
しかし、数値としては 0.0 と -0.0 、同じ「ゼロ」でありますから、== で比較すると、True が返ります。何なの、ソレ !?

では、アトムの比較を行う、is で比較をしたら区別が出来るんじゃないか、と思ったのですが、fx-CG50 の場合、これはアカンのですネ。

>>> -0.0 is 0.0 
False
>>> -0.0 is -0.0 
False
>>> 0.0 is 0.0 
False


なんと、0.0 という同じ値を比較しても、False となりますネ。「どうなっとんジャイ、ワレ !」

この謎を解く鍵は、アトムのid を取得する id() でした。

>>> id(-0.0)
2351257904
>>> id(-0.0)
2351258160 
これは一例ですが、同じ操作をしているのに、毎回、id が変化します。

idという値、どうもアトムを保持するheap空間のテーブルインデクス、有り体に言えばポインタの様な値らしい。
これが毎度違う値になるというのは、毎度、浮動小数点数値アトムが振り出されてheapに作られる、という具合の様ですネ。
PCのpython では、0.0 は一意に決まった数値アトムという扱いなので、何度操作しても変化する事はなさそうですが、電卓の方は、そこまで手が回っていないのかも知れません。
( 但し、当方の fx-CG50 upython は、チョット古めです )

こうなると、0.0 と -0.0 の区別は難しいなァ、と思っていたのですが、(数値アトムを)文字列に変換する関数 str() がありました。これを使うと、0.0 , -0.0 、両方とも表示通りに文字列になるのです。これで、0.0 と -0.0 の区別が出来ますネ、ヨカッタ、ヨカッタ。

そんな事が解ったので、自家製の copysign() として、チョット苦し紛れなコードを開陳した次第です。「ご査収ください」

#  copysign() like something ...
def  csign(x, y) :
  if y == 0.0 :
    if str(y) == '-0.0' :
      return -abs(x)
    else :
      return abs(x)
  else :
    if y < 0 :
      return -abs(x)
    else :
      return abs(x)

本来なら math.copysign() と、math module にあるものではありますが、後から追加するわけにも行かないので、自家製cmath module の中に、邪魔にならないよう csign() と名前を変えて導入致しました。

これを使ってcmath.sqrt() もK 様提案の方法にしたのですが、cmat.csign() が足を引っ張っているので、速度は余り期待できません、ハイ。

さて、こうした具合で動いている upython ではありますから、以前に、電卓喫茶様が「fx-CG50 upython で 色指定をタプルで書くと、速度が激落ちする」という報告をされておりました。これは、毎度、数値を含むタプルを生成して、heapに置いているから、時間が掛かっているのではないかという推測をしたのですが、少しは判断材料になったのかも、と思う所です。色指定のタプルを予め作っておき、適当な変数名にbindして、変数を呼び出す様にする事で、オーバーヘッドが大分少なくなる模様です。


2024年9月28日土曜日

fx-CG50 で Biomorph を描く

 Sentaro様から「面白いモノはナーイ ?」との事で、fx-CG50 upython をしばき倒す(?) 「Pickovers' Biomorph」のコードを動かしてみました。

当方が、Pickovers' Biomorph を知った、そのネタ元と言いますと、昔、図書館で読んだ、日経サイエンス誌の連載「コンピューター・リクリエーション」(A. K. Dewdney) なのですが、Pickover biomorphs で検索すると、およその所が解ると思います。

Mandelbrot set graphics の作業の様ですが、少し異なる部分もあります。
詳細はコードをご参照ください。

Pickovers' Biomorphs の場合、繰り返す計算式を色々と変更する事で、描かれる画像が多様に変化します。
このコードでは、

    z = z*z+c
を繰り返しますが、これを、例えばつぎの行にある様に、
    z = cmath.sin(z*z)-c
とかに変更すると、画像が大きく変化するのです。

複素数平面の座標値に数式を繰り返し適用するため、複素数を扱う関数が必要になりますが、残念ながら、fx-CG50 には cmath module が用意されておりません。

そこで、急ごしらえで cmath module を用意しました。 残念ながら、asin() などはまだ、用意できておりませんが、チョット遊ぶなら、この辺りから始めても十分であると思います。 

実行は、プログラムを読み込んだ後、

biom() 

と入力する事で実行されます。

ループ中の数式を変更する事でも、画像が大きく変化するのですが、定数 c を変える事でも、微妙に画像が変化します。
定数 c も複素数ですが、biom(c.real, c.imag) の様に、実部と虚部をカンマで分けて指定する事で与えられます。

残念ながら、cmath module が system binary ではなく、実行速度が大変遅いという哀しい部分はありますが、
じわじわとグラフィクスが描かれる様を眺めるのも、手のひらで動く電卓ならではの愉しみであると思います。

 

追記 on 2024-10-05

過日、K 様にコメント戴き、sqrt() を更新いたしました。
math.copysign() が fx-CG50 には無いため、自家製の copysign() もどき csign() を付け足しましたヨ。これにより、計算速度が向上したという具合には行きませんが、ネタとしては色々と面白かったので、後日、別記したく思います。

謝謝 !


リスト  biom.py

# title : biom.py - Pickovers' Biomorph for fx-CG50
# begin : 2024-09-28 19:33:39

from casioplot import *
import math
import cmath

def  biom(re=0, im=0) :
  width  = 383
  height = 191

  xs=-3.8
  xe= 3.8
  ys=-1.9
  ye= 1.9
 
  c = re - im*1j

  #  Biomorph
  for j in range(height):
    for i in range(width):
      z = (i*(xe-xs)/width +xs) + 1j*(j*(ys-ye)/height+ye)
      #  repeating core
      k = 0
      while abs(z) <= 10 and k < 10:
        z = z*z+c
        #z = cmath.sin(z*z)-c
        k=k+1
      #  
      if abs(z.real) < 10 or abs(z.imag) < 10 :
        set_pixel(int(i), int(j))

      #  show graphix progressively
      show_screen()


リスト  cmath.py

##  title : [WIP] cmath module for fx-CG50
## begin : 2024-09-28 00:38

import math

# copysign() like something ...
def csign(x, y) :
if y == 0.0 :
if str(y) == '-0.0' :
return -abs(x)
else :
return abs(x)
else :
if y < 0 :
return -abs(x)
else :
return abs(x)

#
def phase(x) :
return math.atan2(x.imag, x.real)

##
def exp(x) :
return pow(math.e, x)

##
def ln(x) :
return math.log(abs(x)) + phase(x)*1j

##
def log(x, base=math.e) :
return ln(x) / ln(base)

## thanks K sama ! on 2024-10-04
def sqrt(x) :
# return pow(x, 0.5)
return math.sqrt((abs(z)+z.real)/2) + 1j* csign(math.sqrt((abs(z)-z.real)/2), z.imag)

##
def sin(c) :
return math.sin(c.real)*math.cosh(c.imag) + (math.cos(c.real)*math.sinh(c.imag))*1j

##
def cos(c) :
return math.cos(c.real)*math.cosh(c.imag) - (math.sin(c.real)*math.sinh(c.imag))*1j

##
def tan(c) :
return sin(c) / cos(c)

2024年9月22日日曜日

python電卓を持っていても余り使っておらんので、暇つぶし

 以前に、fx-CG50 を買って、先日、ようやく python が使える様にアップデートした所。
「慣らし運転」ではありませんが、pythonの計算速度を見るつもりで、簡単なループ計算を実行したという次第。

プログラムは以下。
冒頭の文字列部分は「コメント」なので、電卓では無用ノ介。本体のループ部分だけを入れて、実行してみてください。


'''
NHK TV 「3ヶ月で学ぶ数学」より。

問題 : 
3桁の整数 ABC (=100*A+10*B+C) について、
+  ABC * 3/4 = BCA
+  BCA * 3/4 = CAB

の関係を満たす整数ABC は、2つある。全てを求めよ。
(中学校の入試問題より)

答え : 

1. 比例式を準備

+  ABC : BCA = 4 : 3
+  BCA : CAB = 4 : 3

2.  比例式を、最小公倍数にて一本に

+  ABC : BCA = 4 : 3 = 16 :12
+  BCA : CAB = 4 : 3 = 12 : 9

よって、
+  ABC : BCA : CAB = 16 : 12 : 9

3. これより、
   「CAB は 9の倍数」→「CAB の各桁の和は 9 の倍数」→「ABC, BCA の各桁の和は 9 の倍数」

4. また、
   「ABC は 9の倍数 and 16の倍数」→「ABC は 16*9の倍数」

+  16*9 = 144 の倍数
   144, 288, 432, 576, 720, 864

5. 一本化した比例式より、
   A >= B >= C

6.  この条件を満たす 144の倍数は、
    432, 864

という具合であった。

しかし、pythonが動く電卓がある事だし 力技で、解いてみたという次第。
(大人気ない)

結果は、

Hit ! 0
Hit ! 432
Hit ! 864

という具合。
1000回ループながらも、瞬時に答えが得られ、ビックリしてしまいました。

'''

for a in range(10) :
    for b in range(10) :
        for c in range(10) :
            abc = a*100+b*10+c
            bca = 100*b+10*c+a
            cab = c*100+a*10+b
            if abc *3/4 == bca :
                if bca *3/4 == cab :
                    print('Hit !', abc)