GoにいればGoに従え(32) math/cmplxをTinyGoで使う、ムムム早合点?

Joseph Halfmoon

前回のキャリーだの、ボローだのの世界はこの老人には慣れ親しんだ世界にて居心地が良かったです。しかし今回使ってみるのは math/cmplxパッケージです。浮動小数点数ですらちょっと敷居が高いのに、そいつらの上に君臨する複素数はできれば避けたいデス。そんなこと考えていたら挙動不審。ムムムこの挙動はどゆこと?早合点よ。

※「GoにいればGoに従え」Go関連記事の総Index

※実機動作は Arm Cortex-M4Fコア登載のNordic nRF52833チップ搭載、みんな大好き BBC micro:bit v2 機にTinyGoのオブジェクトを書き込んで行っています。

go言語の複素数型

以下の御本家ドキュメントを参照させていただくに、

The Go Programming Language Specification Version of Aug 2, 2023

Go言語は以下2種類の複素数型をもつようです。

    • complex64
    • complex128

complex64型は、実部と虚部にそれぞれ float32型をとるもの。complex128型は、同様にfloat64型をとるものであります。

そして複素数型のリテラル値では、虚数単位として i を使うと。こんな感じ。

1.2 + 3.4i

数学風の表記です。どこかの言語が、電子電気工学系におもねったのか虚数単位に j を使っているのとは一線を画しておりますな(もっと言えば、i でも j でも気にせんという心の広い?処理系も無いわけでないですが。)

math/cmplx パッケージ

さて、今回使用してみますのは、go言語の標準ライブラリ math/cmplx であります。複素数型の加減乗除などは特にパッケージなど呼ばずともフツーに書き表せるので、各種超越関数などを計算したいときに呼び出すものであります。大は小を兼ねる、ということなのか

complex128型

の引数に対して作用するようになっています。結果はcomplex128またはfloat64型。

そしてTinyGoの対応状況を以下のページから確認すると

Packages supported by TinyGo

Importable=yes、Passes test=yesということであります。安心して計算に使える筈。

今回実験のTinyGoソースコード

だいたいGo言語で、複素数演算なども書いたこともなかったので、例題を参考にそろそろと書いてみたのが以下です(修正済のOKなやつデス。最初に実験したコードにはダメなところがあった)

package main

import (
    "fmt"
    "math"
    "math/cmplx"
)

func main() {
    x := math.Cos(math.Pi / 4)
    y := math.Sin(math.Pi / 4)
    fmt.Printf("x=%.3f y=%.3f\n", x, y)
    c0 := complex(x, y)
    c1 := 1.0 + 1.0i
    fmt.Printf("c0=%.3f c1=%.3f\n", c0, c1)
    fmt.Printf("abs(%.3f)=%.3f\n", c0, cmplx.Abs(c0))
    fmt.Printf("abs(%.3f)=%.3f\n", c1, cmplx.Abs(c1))
    r0, t0 := cmplx.Polar(c0)
    r1, t1 := cmplx.Polar(c1)
    fmt.Printf("(r0, t0)=%.3f %.3f*PI\n", r0, t0/math.Pi)
    fmt.Printf("(r1, t1)=%.3f %.3f*PI\n", r1, t1/math.Pi)
}
実験結果

以下のコマンドラインにて、上記のソース(の元のダメなやつ)をビルドしてUSB接続したターゲット機BBC micro:bit v2 に書き込みました(該当のプロジェクトフォルダ内で。)

$ tinygo flash --target microbit-v2

いつものようにシリアルモニタをmicro:bit v2のUSBシリアル接続先に向けておけば、動作結果を観察することができます。その結果が以下に。

complexResults

だいたいのところは、期待通りなのだけれども、上記の黄色のマーカのところが「期待と異なり」ます。c0のabsを取っているところなので、黄色のマーカのところにはその1行上と同様

0.707+0.707i

と表示されると思っていたのですが違いました。でもその後のcmplx.Abs(c0)の計算結果は期待通りなので、math.cmplxによる複素数型の計算は間違っていないデス。

念のため、問題個所のソースのキャプチャ。黄色のマーカが該当部分(ダメなところですけど。)complexSRC

math/cmplx型の問題ではなく、どうも fmtパッケージのPrintfの使い方の問題のような気がしてきました。よく見ろよ、自分。

%.3f と書くべきところ %3.f と書いてました

修正して実行しなおせば、ほれこのように。complexResultsOK

問題ないじゃん、人騒がせな。

GoにいればGoに従え(31) math/bitsをTinyGoで使う、その2 へ戻る

GoにいればGoに従え(33) byte型、bytes.Buffer型、TinyGo へ進む