きっかけ
ある処理の実現でビット演算を組み込もうとしたら、PowerAutomateには指数関数(pow/powerなど)・論理演算(論理和・論理積・排他論理和など)・2⇔10進数変換などの関数が提供されてないと分かりましたorz
解決策として、OfficeScriptやAzureを用いるといった記事は見つかったのですが、これらを使わずに実現したかったので、子フローで関数作成することにしました。
ループを回せばシンプルに作れますが処理時間が長くなってしまうので、よく使いそうな条件の場合(基数2、15乗まで)はバイパス処理で高速処理してます。
PowerAutomate:子フローの作成 をベースに指数関数を子フロー化したので内容を紹介します。
その他の関数実装は以下をご参照ください。
本処理では、PowerAutomate:整数型の最大値を調べてみた で確認した内容をふまえて上限値エラー設定しています。
ビット演算はQiitaに記事がたくさんあるので、Qiita:「ビット演算」検索結果 をご参照ください。
このフローをつくると…
子フローで基数と指数を指定すると指数計算してメインフローに応答します。
指数はゼロか正の値のみ対応します。
全体像
①トリガ設定
親フローからは2個の引数を渡します。
| 名前 | 種類 | パラメータ名 | 必須/非必須 | 備考 |
|---|---|---|---|---|
| 基数 | 数値 | number | 必須 | 0以外の整数の前提 |
| 指数 | 数値 | number_1 | 必須 | 0以上の整数の前提 |
②変数初期化
『変数を初期化する』で以下2個の変数を仮値で設定します。
| 名前 | 種類 | 初期値 |
|---|---|---|
| 指数 | 整数 | 0 |
| 返り値 | 整数 | 1 |
③処理ロジック
自分が頻繁に使う2の指数のうち16乗未満は、②-6)~10)のバイパス処理でループ回避した対応を行ってます。

③-1) 基数≠0かつ指数が0以上?
『条件』で入力値が正常か判定をします。
<And条件1>
- 左辺: (式)isInt(string(triggerBody()['number']))
- 条件:次の値に等しい
- 右辺: (値)true
<And条件2>
- 左辺: (式)triggerBody()['number']
- 条件:次の値に等しくない
- 右辺: (値)0
<And条件3>
- 左辺: (式)isInt(string(triggerBody()['number_1']))
- 条件:次の値に等しい
- 右辺: (値)true
<And条件4>
- 左辺: (式)triggerBody()['number_1']
- 条件:次の値以上
- 右辺: (値)0
③-2) 指数変数の設定
『変数の設定』で指数変数を入力値に設定します。
- 値:
@{int(triggerBody()['number_1'])}
③-3) 呼び出し元へ応答(対応外入力値)
『PowerApp または Flow に応答する』で返り値をエラーメッセージで設定します。
- 出力の種類:数
- 返り値:エラー:基数は0以外、指数は0以上の整数で指定してください
③-4) 終了
『終了』で処理を停止します。
- メッセージ:対応外入力値
③-5) 指数が0より大きい?
『条件』で指数が0より大きいか判定をします。
- 左辺:
variables('指数') - 条件:次の値より大きい
- 右辺: (値)0
③-6) 基数=2?(高速化対応)
基数2の計算は個別ロジックで高速化処理するため、『条件』で基数が2か判定をします。
- 左辺:
@triggerBody()['number'] - 条件:次の値に等しい
- 右辺: (値)2
③-7) 1~15回乗算作成(ループ1回対策)
『作成』で2を最大15回乗算します。(美しくないけど処理は速い…)
- 入力:
div(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul(mul( variables('返り値'), if(greater(variables('指数'),0),triggerBody()['number'],1) ), if(greater(variables('指数'),1),triggerBody()['number'],1) ), if(greater(variables('指数'),2),triggerBody()['number'],1) ), if(greater(variables('指数'),3),triggerBody()['number'],1) ), if(greater(variables('指数'),4),triggerBody()['number'],1) ), if(greater(variables('指数'),5),triggerBody()['number'],1) ), if(greater(variables('指数'),6),triggerBody()['number'],1) ), if(greater(variables('指数'),7),triggerBody()['number'],1) ), if(greater(variables('指数'),8),triggerBody()['number'],1) ), if(greater(variables('指数'),9),triggerBody()['number'],1) ), if(greater(variables('指数'),10),triggerBody()['number'],1) ), if(greater(variables('指数'),11),triggerBody()['number'],1) ), if(greater(variables('指数'),12),triggerBody()['number'],1) ), if(greater(variables('指数'),13),triggerBody()['number'],1) ), if(greater(variables('指数'),14),triggerBody()['number'],1) ), if(greater(variables('指数'),15),triggerBody()['number'],1) ) ,triggerBody()['number'])
③-8) 返り値の設定
『変数の設定』で返り値に③-7の計算結果を設定します。
- 値:
@{outputs('1~15回乗算作成(ループ1回対策)')}
③-9) 減算指数作成
『作成』で指数変数が15より大きい場合は「指数-15」、それ以外は0を設定します。
- 入力:
if(greater(variables('指数'),15),sub(variables('指数'),15),0)
③-10) 指数減算設定
『変数の設定』で指数に③-9の計算結果を設定します。
- 値:
@{outputs('減算指数作成')}
③-11) 指数がなくなるまで繰り返し
『Do Until』で指数が0以下になるまで繰り返し処理します
- 左辺:
@variables('指数') - 条件:次の値以下
- 右辺: (値)0
③-12) 一時退避変数作成
『作成』で計算処理前の返り値変数を退避格納します。
- 入力:
@{variables('返り値')}
③-13) 返り値を積算
『変数の設定』で一次退避変数に基数を乗算した計算結果を設定します。
- 値:
mul(outputs('一時退避変数作成'),triggerBody()['number'])
③-14) 返り値桁数は16桁未満かつ返り値更新されてる?
『条件』で返り値計算結果と桁数判定をします。
三点メニュー→「実行条件の構成」で「に失敗しました」にもチェックを入れます。
<And条件1>
- 左辺: (式)length(string(variables('返り値')))
- 条件:次の値未満
- 右辺: (値)16
<And条件2>
- 左辺: (値)'@variables('返り値')'
- 条件:次の値に等しくない
- 右辺: (値)'@outputs('一時退避変数作成')'
実行条件の構成を変えることで「③-13) 返り値を積算」がoverflow時のInvalidTemplateエラーなどで失敗しても停止せず、And条件2にマッチしないケースとして扱われます。
③-15) 返り値変数の設定(桁あふれ)
『変数の設定』で返り値を0に設定します。
- 値:
0
③-16) 指数変数の設定(桁あふれ)
『変数の設定』で指数を0に設定します。
- 値:
0
③-17) 指数を減らす
『変数の値を減らす』で指数を1減らします。
- 名前:指数
- 値:
1
④応答設定
『PowerApp または Flow に応答する』で返り値変数を返り値として設定します。
返り値が0の場合、積算ループで桁あふれとなった場合なのでエラー文言を設定します。
- 出力の種類:数
- 処理ステータス:(式)
if(equals(variables('返り値'),0),'エラー:計算桁数が大きすぎます(15桁超)',variables('返り値'))


