0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PowerAutomate子フロー:論理演算

0
Posted at

きっかけ

ビット演算の組み込み実現に向け、PowerAutomateで提供されない論理演算をPowerAutomate:子フローの作成 をベースに関数化しました。
2進数⇔10進数変換の子フロー呼び出しを使えばシンプルに作れますが処理時間が長くなってしまうので、よく使いそうな条件の場合(整数65535、16ビットまで)は子フローを使わないよう高速処理してます。

その他の関連関数の実装は以下をご参照ください。

本フロー内では10進数⇔2進数変換を行うため、PowerAutomate子フロー:10進数→2進数変換PowerAutomate子フロー:2進数→10進数変換を利用してます。

このフローをつくると…

子フローで2つの整数と演算種類(論理和・論理積・排他論理和)を指定すると指定した演算種類を計算してメインフローに応答します。
引数は PowerAutomate:整数型の最大値を調べてみた ふまえ15桁まで対応してます。

<親フローの実装例>

<親フローの処理結果>

子フロー全体像

構成は以下の通りです。

①トリガ設定

親フローからは3個の引数を渡します。

名前 種類 パラメータ名 必須/非必須 備考
入力値1 数値 number 必須 0以上16桁未満の整数
入力値2 数値 number_1 必須 0以上16桁未満の整数
演算種類 数値 number_2 未指定 or 0:論理和、1:論理積、2:排他論理和

②変数初期化

『変数を初期化する』で以下4個の変数を設定します。

名前 種類 初期値
入力値1 整数 0
入力値2 整数 0
演算種類 整数 0
返り値 整数 0

③スコープ1:入力チェック


③-1) 条件:記載例

『条件』で入力値3つが指定範囲内かを判定します。

<And条件1>

  • 左辺: (式)isInt(string(triggerBody()?['number']))
  • 条件:次の値に等しい
  • 右辺: (式)true

<And条件2>

  • 左辺: (式)isInt(string(triggerBody()?['number_1']))
  • 条件:次の値に等しい
  • 右辺: (式)true

<And条件3>

  • 左辺: (式)isInt(string(if(equals(triggerBody()?['number_2'],null),0,triggerBody()?['number_2'])))
  • 条件:次の値に等しい
  • 右辺: (式)true

<And条件4>

  • 左辺: (式)int(string(triggerBody()?['number']))
  • 条件:次の値以上
  • 右辺: (値)0

<And条件5>

  • 左辺: (式)length(string(triggerBody()?['number']))
  • 条件:次の値未満
  • 右辺: (値)16

<And条件6>

  • 左辺: (式)int(string(triggerBody()?['number_1']))
  • 条件:次の値以上
  • 右辺: (値)0

<And条件7>

  • 左辺: (式)length(string(triggerBody()?['number_1']))
  • 条件:次の値未満
  • 右辺: (値)16

<And条件8>

  • 左辺: (式)createArray(0,1,2)
  • 条件:次の値を含む
  • 右辺: (式)int(string(if(equals(triggerBody()?['number_2'],null),0,triggerBody()?['number_2'])))

③-2) 入力値1変数の設定

『変数の設定』で入力値1を引数入力値に設定します。

  • 式:@{int(string(triggerBody()?['number']))}

③-3) 入力値2変数の設定

『変数の設定』で入力値2を引数入力値に設定します。

  • 式:@{int(string(triggerBody()?['number_1']))}

③-4) 演算種類変数の設定

『変数の設定』で演算種類を引数入力値(未指定の場合は0)に設定します。

  • 式:@{int(string(if(equals(triggerBody()?['number_2'],null),0,triggerBody()?['number_2'])))}

③-5) エラー応答を返す

『PowerApp または Flow に応答する』で応答値を設定します。
(正常終了時の応答が数値のため、種類は数値指定してますが文字をいれてます💦)

  • 出力の種類:数値
  • 名称:返り値
  • 値:入力値1,2は0以上の15桁、演算種別は0-2の範囲の整数を指定してください。

③-6) 終了

『終了』で処理を停止します。

  • 状態:失敗
  • メッセージ:入力値1,2は0以上の15桁、演算種別は0-2の範囲の整数を指定してください。

④スコープ2:演算処理

入力値1-2の両方が65535(16ビット)以下の場合は子フローを使わない高速処理(項番2~12の処理)、それ以外は子フロー利用する処理(項番13~29の処理、やや時間かかります)に分岐してます。


④-2) 2進数文字列1作成

『作成』で入力値1の2進数変換した固定長16桁文字列を作成します。

  • 入力:@{if(greater(add(mod(variables('入力値1'),65536),1),32768),1,0)}@{if(greater(add(mod(variables('入力値1'),32768),1),16384),1,0)}@{if(greater(add(mod(variables('入力値1'),16384),1),8192),1,0)}@{if(greater(add(mod(variables('入力値1'),8192),1),4096),1,0)}@{if(greater(add(mod(variables('入力値1'),4096),1),2048),1,0)}@{if(greater(add(mod(variables('入力値1'),2048),1),1024),1,0)}@{if(greater(add(mod(variables('入力値1'),1024),1),512),1,0)}@{if(greater(add(mod(variables('入力値1'),512),1),256),1,0)}@{if(greater(add(mod(variables('入力値1'),256),1),128),1,0)}@{if(greater(add(mod(variables('入力値1'),128),1),64),1,0)}@{if(greater(add(mod(variables('入力値1'),64),1),32),1,0)}@{if(greater(add(mod(variables('入力値1'),32),1),16),1,0)}@{if(greater(add(mod(variables('入力値1'),16),1),8),1,0)}@{if(greater(add(mod(variables('入力値1'),8),1),4),1,0)}@{if(greater(add(mod(variables('入力値1'),4),1),2),1,0)}@{mod(variables('入力値1'),2)}

④-3) 2進数文字列2作成

『作成』で入力値2の2進数変換した固定長16桁文字列を作成します。

  • 入力:@{if(greater(add(mod(variables('入力値2'),65536),1),32768),1,0)}@{if(greater(add(mod(variables('入力値2'),32768),1),16384),1,0)}@{if(greater(add(mod(variables('入力値2'),16384),1),8192),1,0)}@{if(greater(add(mod(variables('入力値2'),8192),1),4096),1,0)}@{if(greater(add(mod(variables('入力値2'),4096),1),2048),1,0)}@{if(greater(add(mod(variables('入力値2'),2048),1),1024),1,0)}@{if(greater(add(mod(variables('入力値2'),1024),1),512),1,0)}@{if(greater(add(mod(variables('入力値2'),512),1),256),1,0)}@{if(greater(add(mod(variables('入力値2'),256),1),128),1,0)}@{if(greater(add(mod(variables('入力値2'),128),1),64),1,0)}@{if(greater(add(mod(variables('入力値2'),64),1),32),1,0)}@{if(greater(add(mod(variables('入力値2'),32),1),16),1,0)}@{if(greater(add(mod(variables('入力値2'),16),1),8),1,0)}@{if(greater(add(mod(variables('入力値2'),8),1),4),1,0)}@{if(greater(add(mod(variables('入力値2'),4),1),2),1,0)}@{mod(variables('入力値2'),2)}

④-4) 演算種類=論理和?

『条件』で演算種類が論理和か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)0

④-5) 論理和

『選択』で、開始では0から16個の配列(0~15)を設定、マップでは2進数文字列1と2進数文字列2を左から1文字ずつ切り出して、いずれかが1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{range(0,16)}
  • マップ:@{if(or(equals(substring(outputs('2進数文字列1作成'), item(), 1),'1'),equals(substring(outputs('2進数文字列2作成'), item(), 1),'1')),1,0)}

マップをテキストモードに切り替えて入力します


④-6) 返り値設定(論理和)

『変数の設定』で「④-5) 論理和」を0番目から順に、値が1の場合は「2の(15-位置)乗」を加算した値を返り値に設定します。

  • 値:(式)@{add(mul(body('論理和')?[0],32768), add(mul(body('論理和')?[1],16384), add(mul(body('論理和')?[2],8192), add(mul(body('論理和')?[3],4096), add(mul(body('論理和')?[4],2048), add(mul(body('論理和')?[5],1024), add(mul(body('論理和')?[6],512), add(mul(body('論理和')?[7],256), add(mul(body('論理和')?[8],128), add(mul(body('論理和')?[9],64), add(mul(body('論理和')?[10],32), add(mul(body('論理和')?[11],16), add(mul(body('論理和')?[12],8), add(mul(body('論理和')?[13],4), add(mul(body('論理和')?[14],2), body('論理和')?[15])))))))))))))))}

④-7) 演算種類=論理積?

『条件』で演算種類が論理積か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)1

④-8) 論理積

『選択』で、開始では0から16個の配列(0~15)を設定、マップでは2進数文字列1と2進数文字列2を左から1文字ずつ切り出して、いずれも1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{range(0,16)}
  • マップ:@{if(and(equals(substring(outputs('2進数文字列1作成'), item(), 1),'1'),equals(substring(outputs('2進数文字列2作成'), item(), 1),'1')),'1','0')}

マップをテキストモードに切り替えて入力します


④-9) 返り値設定(論理積)

『変数の設定』で「④-8) 論理積」を0番目から順に、値が1の場合は「2の(15-位置)乗」を加算した値を返り値に設定します。

  • 値:(式)@{add(mul(int(body('論理積')?[0]),32768), add(mul(int(body('論理積')?[1]),16384), add(mul(int(body('論理積')?[2]),8192), add(mul(int(body('論理積')?[3]),4096), add(mul(int(body('論理積')?[4]),2048), add(mul(int(body('論理積')?[5]),1024), add(mul(int(body('論理積')?[6]),512), add(mul(int(body('論理積')?[7]),256), add(mul(int(body('論理積')?[8]),128), add(mul(int(body('論理積')?[9]),64), add(mul(int(body('論理積')?[10]),32), add(mul(int(body('論理積')?[11]),16), add(mul(int(body('論理積')?[12]),8), add(mul(int(body('論理積')?[13]),4), add(mul(int(body('論理積')?[14]),2), int(body('論理積')?[15]))))))))))))))))}

④-10) 演算種類=排他論理和?

『条件』で演算種類が排他論理和か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)2

④-11) 排他論理和

『選択』で、開始では0から16個の配列(0~15)を設定、マップでは2進数文字列1と2進数文字列2を左から1文字ずつ切り出して、値が異なる場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{range(0,16)}
  • マップ:@{if(not(equals(substring(outputs('2進数文字列1作成'), item(), 1),substring(outputs('2進数文字列2作成'), item(), 1))),'1','0')}

マップをテキストモードに切り替えて入力します


④-12) 返り値設定(排他論理和)

『変数の設定』で「④-11) 排他論理和」を0番目から順に、値が1の場合は「2の(15-位置)乗」を加算した値を返り値に設定します。

  • 値:(式)@{add(mul(int(body('排他論理和')?[0]),32768), add(mul(int(body('排他論理和')?[1]),16384), add(mul(int(body('排他論理和')?[2]),8192), add(mul(int(body('排他論理和')?[3]),4096), add(mul(int(body('排他論理和')?[4]),2048), add(mul(int(body('排他論理和')?[5]),1024), add(mul(int(body('排他論理和')?[6]),512), add(mul(int(body('排他論理和')?[7]),256), add(mul(int(body('排他論理和')?[8]),128), add(mul(int(body('排他論理和')?[9]),64), add(mul(int(body('排他論理和')?[10]),32), add(mul(int(body('排他論理和')?[11]),16), add(mul(int(body('排他論理和')?[12]),8), add(mul(int(body('排他論理和')?[13]),4), add(mul(int(body('排他論理和')?[14]),2), int(body('排他論理和')?[15]))))))))))))))))}

④-13) 子フロー:2進数変換(1)

『子フローの実行』で子フロー:10進数→2進数変換 を呼び出し、入力値1を2進数変換します。

子フロー:10進数→2進数変換
入力日付:@{variables('入力値1')}

子フローの詳細は PowerAutomate子フロー:10進数→2進数変換 を参照してください。


④-14) 子フロー:2進数変換(2)

『子フローの実行』で子フロー:10進数→2進数変換 を呼び出し、入力値2を2進数変換します。

子フロー:10進数→2進数変換
入力日付:@{variables('入力値2')}

子フローの詳細は PowerAutomate子フロー:10進数→2進数変換 を参照してください。


④-15) 文字列長配列作成

『作成』で入力値1、または入力値2のうち文字列数の長いものに合わせて、文字数分の配列を作成し、値には0から連番を振ります。(配列値:0,1,2,…,N)

  • 値:@{range(0,if(less(length(outputs('子フロー:2進数変換(1)')?['Body']?['返り値']),length(outputs('子フロー:2進数変換(2)')?['Body']?['返り値'])),length(outputs('子フロー:2進数変換(2)')?['Body']?['返り値']),length(outputs('子フロー:2進数変換(1)')?['Body']?['返り値'])))}

④-16) 引数1配列選択

『選択』で、開始では「④-15) 文字列長配列」を設定、マップでは「④-13) 子フロー:2進数変換(1)」の返り値を右から1文字ずつ切り出して、値が1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{outputs('文字列長配列作成')}
  • マップ:@{if(greaterOrEquals(item(),length(outputs('子フロー:2進数変換(1)')?['Body']?['返り値'])),0,int(substring(outputs('子フロー:2進数変換(1)')?['Body']?['返り値'],sub(sub(length(outputs('子フロー:2進数変換(1)')?['Body']?['返り値']),item()),1),1)))}

マップをテキストモードに切り替えて入力します


④-17) 引数2配列選択

『選択』で、開始では「④-15) 文字列長配列」を設定、マップでは「④-14) 子フロー:2進数変換(2)」の返り値を右から1文字ずつ切り出して、値が1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{outputs('文字列長配列作成')}
  • マップ:@{if(greaterOrEquals(item(),length(outputs('子フロー:2進数変換(2)')?['Body']?['返り値'])),0,int(substring(outputs('子フロー:2進数変換(2)')?['Body']?['返り値'],sub(sub(length(outputs('子フロー:2進数変換(2)')?['Body']?['返り値']),item()),1),1)))}

マップをテキストモードに切り替えて入力します


④-18) 演算種類=論理和?(17bit以上)

『条件』で演算種類が論理和か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)0

④-19) 論理和選択

『選択』で、開始では「④-15) 文字列長配列」を設定、マップでは「④-16) 引数1配列選択」「④-17) 引数2配列選択」の開始で指定する位置の値のいずれかが1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{outputs('文字列長配列作成')}
  • マップ:@if(or(equals(body('引数1配列選択')?[item()],1),equals(body('引数2配列選択')?[item()],1)),1,0)

④-20) 子フロー:論理和の10進数変換

『子フローの実行』で子フロー:2進数→10進数変換 を呼び出し、「④-19) 論理和選択」を逆順に文字列化した2進数を10進数変換します。

  • 子フロー:2進数→10進数変換
  • 2進数:@{join(reverse(body('論理和選択')),'')}

子フローの詳細は PowerAutomate子フロー:2進数→10進数変換 を参照してください。


④-21) 返り値設定(17bit以上の論理和)

『変数の設定』で「④-20) 子フロー:論理和の10進数変換」を返り値に設定します。

  • 値:(式)@{int(body('子フロー:論理和の10進数変換')?['返り値'])}

④-22) 演算種類=論理積?(17bit以上)

『条件』で演算種類が論理積か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)1

④-23) 論理積選択

『選択』で、開始では「④-15) 文字列長配列」を設定、マップでは「④-16) 引数1配列選択」「④-17) 引数2配列選択」の開始で指定する位置の値のいずれも1の場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{outputs('文字列長配列作成')}
  • マップ:@if(and(equals(body('引数1配列選択')?[item()],1),equals(body('引数2配列選択')?[item()],1)),1,0)

④-24) 子フロー:論理積の10進数変換

『子フローの実行』で子フロー:2進数→10進数変換 を呼び出し、「④-23) 論理積選択」を逆順に文字列化した2進数を10進数変換します。

  • 子フロー:2進数→10進数変換
  • 2進数:@{join(reverse(body('論理積選択')),'')}

子フローの詳細は PowerAutomate子フロー:2進数→10進数変換 を参照してください。


④-25) 返り値設定(17bit以上の論理積)

『変数の設定』で「④-24) 子フロー:論理積の10進数変換」を返り値に設定します。

  • 値:(式)@{int(body('子フロー:論理積の10進数変換')?['返り値'])}

④-26) 演算種類=排他論理和?(17bit以上)

『条件』で演算種類が排他論理和か判定をします。

  • 左辺: (式)variables('演算種類')
  • 条件:次の値に等しい
  • 右辺: (値)2

④-27) 排他論理和選択

『選択』で、開始では「④-15) 文字列長配列」を設定、マップでは「④-16) 引数1配列選択」「④-17) 引数2配列選択」の開始で指定する位置の値が異なる場合は1、それ以外は0を返すよう設定します。

  • 開始:(式)@{outputs('文字列長配列作成')}
  • マップ:@if(not(equals(body('引数1配列選択')?[item()],body('引数2配列選択')?[item()])),1,0)

④-28) 子フロー:排他論理和の10進数変換

『子フローの実行』で子フロー:2進数→10進数変換 を呼び出し、「④-27) 排他論理和選択」を逆順に文字列化した2進数を10進数変換します。

  • 子フロー:2進数→10進数変換
  • 2進数:@{join(reverse(body('排他論理和選択')),'')}

子フローの詳細は PowerAutomate子フロー:2進数→10進数変換 を参照してください。


④-29) 返り値設定(17bit以上の排他論理和)

『変数の設定』で「④-28) 子フロー:排他論理和の10進数変換」を返り値に設定します。

  • 値:(式)@{int(body('子フロー:排他論理和の10進数変換')?['返り値'])}

⑤応答設定

『PowerApp または Flow に応答する』で応答値を設定します。

  • 出力の種類:数値
  • 名称:返り値
  • 値:@variables('返り値')
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?