この記事は、2024年1月に部内向けに書いたブログを外部公開向けに書き直したものです。
はじめに
こんにちは。koukawa_ppです。
さて、小数を分数で近似することをやったことはありますでしょうか。
これは有理数でも無理数でも、有用なテクニックとして知られていますね。
無理数の場合は、ある無理数をよく近似している分数を求めることだったり、有理数の場合はより簡単に表現できる分数を探すことで、小数を分数に近似する例をよく見かけると思います。
とくに無理数の場合は、例えば円周率の近似値がよく で与えられるなど、かなりの近似のテクニックが披露されてきました。
でもこのブログ記事のタイトルは、「分数『を』近似するアプリを作る」です。
分数それ自体が明確な有理数を表しているのだから、それ以上どうやって分数を他の値に近似するのだ、と思われるかもしれません。
ただ、こういった経験をしたことはありませんか。
ここでの値はおおよそ です。
まあこんなあからさまな例はないと思います。
ただ、「おおよそ」と言っておいてなぜこんな細かい数字なのだ、と多くの方は思われたと思います。
このように分子と分母の両方が大きな数だった場合、その近似値を知りたい場合がありますよね。そう、あるんです。
これを自分の好きな程度に近似してくれたら、こんなに便利なことはありません。
そこで、今回の「分数を近似するアプリ」を作るに至ったわけです。
なお、今回のファイルは こちらの GitHub リポジトリ からご覧いただけます。
開発環境
- Windows 10 Home 64bit
- Visual Studio Code
- Python 3.10.11
そもそも分数の近似とは?
近似という操作自体有用なテクニックであることには変わりないのですが、分数は二つの整数(ないし少なくとも一つは基本的に正整数)という非常に簡便な形であらわされているので、これ以上分かりやすい形にするということ自体あまり考えられないのは事実です。
では次のように考えてみましょう。
ふたつの正整数 があるとします。そして、指定された桁数以下の正整数 があるとします。
この4つの正整数について、
が最小となる正整数 を見つけられれば、それが定められた精度において最も元の数 を表現している正整数の組み合わせではないか、と言えます。
具体例として、今回の で考えます。
まず、指定された桁数以下で2以上の分母を持つ分数について、 以下の値のうち最大の値と、 より大きい値のうち最小の値を求めます。
これらを全て列挙したうえで、最も との差の絶対値が小さいような値を求める、というわけです。
例えば分母、分子いずれも一桁と指定した場合、 と最も(数直線上で)近い数字は次のように求められます。
| 分母 | 以下の値の最大値 | より大きい値の最小値 |
|---|---|---|
では、これらの値について、差の絶対値を求めます。
| 比較する値 | 差の絶対値 | 分母をそろえた差の絶対値 |
|---|---|---|
このことから、上記の比較する値のうち、一番 に近いのは であると分かるので、今回求めるのは となります。
このプログラムを使うことにより、 を一桁分の一桁にすると が最も近いということが分かるので、 はおよそ であるということが分かりますね。
と言われるより、 と言われた方が分かりやすくありませんか?
それを実現しているのがこのアプリのうち「分数近似」という機能に実装しているものです。
なお、この分数近似に関してはこの記事の最後の方でお試しできますので、よろしければ触っていただければと思います。
flet
次に、flet についてご紹介します。これは、Python で GUIアプリケーションを開発できるPythonのライブラリです。
このライブラリの優秀な点は、Windows, macOS や Web のみならず、Android や iOS も開発できるという点です。
そもそも flet が Flutter をもとにしており、Flutter が Windows, macOS, Web, Android および iOS をサポートしているので、flet もこれらをサポートできているということになります。
アプリの紹介
ではここからアプリの紹介をしていこうと思います。
とりあえず flet run というコマンドを実行すると、次のようなウィンドウが出てきます。

おおよその構造は上の通りです。
ボトムナビゲーションバーを基本として、分数についての様々な機能を実装しています。
これら機能についてざっくり説明します。
分数近似
二つ前のセクションで説明したものです。
指定した桁数の精度以下で、与えられた分数を近似します。
例えば以下の例では、 を、二桁分の二桁までの精度で近似した場合の結果です。

このように、二桁分の二桁で を近似した場合は、 が最も近い値であると求めることができました。
ちなみに実装は、frac_approx.py にあります。
帯分数⇔仮分数
これ以降3つはいわばおまけです。
これは小学校のころにやった懐かしいもので、帯分数と仮分数を相互に変換できるツールです。
僕の肌感ですが、年を取るにつれて、1より大きい分数を扱わなくなり、その感じで帯分数がフェードアウトしていったような感じがしています。
ただ実際は1より大きい分数を扱う場合もありますから、帯分数として整数部分と小数部分を表記できるのはいいことですね。
しかし帯分数を使わなくなっていった理由としてネットでちょっと調べてみて納得したのは、帯分数の形で整数と分数を表記すると、掛け算記号が省略されているように見えてしまうという不都合があるからという点です。つまり、
のどちらになるのかが曖昧になるということです。
とはいえ、ここではとりあえず小数部分を表す分数を取得するために、アプリの機能の一つとして実装しました。

使い方は簡単で、左辺が仮分数、右辺が帯分数になっているので、
帯分数に変換したい場合は左辺を、
仮分数に変換したい場合は右辺を編集すると、
それに対応する値を求めて出してくれます。
約分
これはその名の通り、与えられた分数を約分する機能です。

上の画像は、143/169 を約分した結果です。
通分
これもその名の通り、与えられた分数を通分する機能です。
正確には、与えられた二つの分数について、
分母が等しくなるように通分する機能になります。

上の画像は、13/11 と 11/13 を通分した結果です。
実行
実行は flet run とすれば OK です。
そうすると、Windows の場合は Windows アプリケーションが立ち上がります。
さらに、flet run -w というコマンドを実行すれば、Web ブラウザで起動することもできます。

これはGoogle Chromeで実行したものです。
また、flet run --android というコマンドで実行すると、ターミナルにQRコードが現れます。
これを、flet アプリをPlayストアなどからインストールし、かつパソコンと同じWi-Fiアクセスポイントに接続したAndroid端末でスキャンすると、fletアプリでそのアプリの実行をすることができます。
ただし、このとき「Error connecting to ~」というエラーメッセージが出ることがあります。
このときは、接続しているWi-Fiのネットワークプロファイルを、「プライベート」にするとうまく行くことがあります。

ご自分のお好きな方法で実行してみてください。
体験版
分数近似について、下に体験版をご用意しました。ぜひ体験してみてください。
おわりに
今回は flet というPythonライブラリでアプリケーションを作ってきました。
もともと.NET MAUIだけを使っていた時は、UIが洗練されているか、という点には一切興味がなかったのですが、Flutterのように他のフレームワークを見てみると、確かにちょっと.NET MAUIのデザインはダサいかな?と
思うことが増えてきたような気がします。
その点もともかく、それよりレイアウトが簡単にできるのが、Flutterなりfletの長所であるようにも感じます。
皆さんもぜひ、Flutterやfletでアプリ開発をしてみてください。
最後までお読みいただき、ありがとうございました。