1

任意の区間で1を、それ以外で-1を示す関数を作ってみた【Desmos】

195
0
$$$$

はじめに

 初めまして、きり梅です。
 この記事は自作した関数の解説と、備忘録と、日記と、噂のMathlogへの興味を足して4で割ったような記事です。
 関数はDesmosに合わせて作っています。Desmos以外のソフトでは使えない可能性があります。
 また、著者は数学にわかであり、用語の誤用や拙いTeXや説明等はご了承ください。

経緯

 最近、Twitterとかで数学の面白い話を聞いたりするとDesmosで実験することがちょくちょくある。
 先日、複数の曲線の一部をつなぎ合わせて一つの関数として扱おうとしたのだが、一部を取り出すのに任意の区間で$1$、それ以外で$0$を示す関数を作り、曲線の関数と乗算して、それを複数用意し加算するという方法を取った。
 これが、どう実装するかだとか、区間端を含むか含まないかの調整だとかでまあまあ面倒だったので、今後また使う可能性を考え、一般化した関数を作ったので、ついでに備忘録と噂のMathlogを試してみようという事でここに書き記しておくことにします。

完成した関数

 とりあえずページをスクロールするのが面倒なときや人もいると思うのでまず完成した関数を置いておきます。

  https://www.desmos.com/calculator/ujvztcqibu

$ f\left( p_{1}, p_{2}, o_{1}, o_{2}, x \right) = \operatorname{sign} \left( \operatorname{sign} \left( \operatorname{sign} \left( p_{1} - p_{2} \right) \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) +\frac{ \operatorname{sign} \left( \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right)}{10} \right) $

 $p_1$が選択区間の左端で、$p_2$が右端です。$p_1-p_2$間が$1$、それ以外は$-1$になります。
 $o_1$$o_2$は代入した数が負か0か正かで$x = p_1,p_2$の時に-1,0,1のどれになるかをそれぞれ指定できます。
 $p_2< p_1$にすることで選択範囲$1$になります。

解説

 原理を説明するために関数に色を付けてわかりやすくします。

$ \operatorname{sign} \left( \operatorname{sign} \left( \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) \color{red} \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) + \color{purple} \frac{ \operatorname{sign} \left( \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right)}{10} \right) $

 の順で解説します。

赤部の解説

$ \color{red} \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| $

 赤部は$点\left(p_1,0\right)$$点\left(p_2,0\right)$を通る直角の折れ線になっています。

まず直角の折れ線を作るため$x$の絶対値を取り、
$\left| x \right|$
折り返し部分を$p_1$$p_2$の中間に合わせる。
$\left| x - \frac{ p_{1} + p_{2} }{2} \right|$
$点\left(p_1,0\right)$$点\left(p_2,0\right)$を通るように高さを合わせる。
$ \color{red} \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| $

 分かりやすくGIFにするとこんな感じです。
赤部GIF 赤部GIF

青部の解説

$ \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) $

 青部の役割は$p_1< p_2$の時は、$-1$を示し、赤部に乗算することで折れ線を上下反転し、$p_2< p_1$になったときには元に戻すことで、区間内選択と区間外選択を切り替えられるようにします。
青部GIF 青部GIF

 ここから赤部と青部を乗算して、$\operatorname{sign}$関数で囲うことで、任意の区間内で$1$を、区間外で$-1$を示す関数になります(以降これを$関数A$とします)。

$関数A$
$ \operatorname{sign} \left( \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) \color{red} \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) $

 が、$\operatorname{sign}\left(0\right)=0$なので、これだと$x=p_1,p_2$の時に数値が$0$になってしまいます。
青部GIF2 青部GIF2

 それで問題無いならいいのですが、今回はここを$-1,0,1$のいずれかに任意で指定できるようにします。

緑部の解説

 $x$$p_1$$p_2$の時にそれぞれどのの数値を示すか指定するために、$変数o_1,o_2$を用意します(取りうる数値は$-1,0,1$のいずれかを想定して話を進めますが実際は実数であればいいです)。

 ここで欲しいのは、$x=p_1$の時に$o_1$を示し、$x=p_2$の時に$o_2$を示す関数です。これを$関数A$に加算すれば$関数A$$0$を示してしまう$p_1,p_2$の地点を正か負か$0$の好きなものに調整できます。

 そのために、$点\left(p_1,o_1\right)$$点\left(p_2,o_2\right)$を通る直線を用意します。これが緑部になります。

$ \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} $

緑部GIF 緑部GIF

紫部の解説

 先ほどの緑部にもう少し手を加えていきます。このまま$関数A$に加算すると関係ないところにも影響を与えてしまうので、まず$\operatorname{sign}$関数で囲い、取りうる値の範囲を$-1\leq x\leq1$に収めます。

$ \operatorname{sign} \left( \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right) $

この状態でも、$関数A$$-1$の部分にこちらの関数の$1$の部分が重なると関数が崩れてしまうので、$関数A$$0$の部分には影響を与えるが、それ以外には影響を与えないように、値の範囲を狭めます。

$ \color{purple} \frac{ \operatorname{sign} \left( \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right)}{10} $

今回は適当に$10$で除算していますが、符号に影響を与えずに$-1< x<1$になるのならどのような方法でもいいです。

紫部GIF 紫部GIF

最後の仕上げの解説

 必要なものは揃ったのでまとめていきます。

$ \operatorname{sign} \left( \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) \color{red} \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) $
$関数A$に紫部を加算して、
$ \operatorname{sign} \left( \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) \color{red} \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) + \color{purple} \frac{ \operatorname{sign} \left( \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right)}{10} $
それを$\operatorname{sign}関数$で囲うだけ。
$ \operatorname{sign} \left( \operatorname{sign} \left( \color{blue} \operatorname{sign} \left( p_{1} - p_{2} \right) \color{red} \left( \left| x - \frac{ p_{1} + p_{2} }{2} \right| - \left| \frac{ p_{1} - p_{2} }{2} \right| \right) \right) + \color{purple} \frac{ \operatorname{sign} \left( \color{green} \frac{ o_{2} - o_{1} }{ p_{2} - p_{1} }\left( x - p_{1} \right) + o_{1} \right)}{10} \right) $

完成GIF 完成GIF

これで完成です。
$p_2$のドットの上にあった黒点が消えていると思います。

もしこれよりスマートにできる方法があったら教えていただけると助かります。

投稿日:202191

この記事を高評価した人

高評価したユーザはいません

この記事に送られたバッジ

バッジはありません。

投稿者

コメント

他の人のコメント

コメントはありません。
読み込み中...
読み込み中