C 論理演算 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(論理演算)
 
1行: 1行:
※このページではC言語にも存在していたという意味で記事タイトルがC ポインタになっていますが、<br />
+
[[C PlusPlus#Cにもあった技術|C++]]へ戻る
 +
 
 +
 
 +
※このページではC言語にも存在していたという意味で記事タイトルがC 論理演算になっていますが、<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
<br />
 
<br />
 
== '''論理演算''' ==
 
== '''論理演算''' ==
論理演算ってのは、普通の算数とは違う和と積の考え方をする分野の仕組みです。これは電子回路でつくられるON・OFFの考え方を数学的に表現しようとするためのモノだと思えばよいと思います。コンピュータも電子回路で構成されていますし、プログラムもメモリの中のON・OFFによって構成される記号の塊です。いわゆる機械語は電子回路のON・OFFによって表現されます。それが2進数であり、発展したものがニーモニック言語でありアセンブラ、16進数表記の考え方に発展し、それを構成するための高水準言語としてCやC++の言語が作られ、コンパイルやリンクの作業翻訳・解析処理によって機械語を生成しているのです。
+
 
 +
論理演算ってのは、普通の算数とは違う和と積の考え方をする分野の仕組みです。これは電子回路でつくられるON・OFFの考え方を数学的に表現しようとするためのモノだと思えばよいと思います。コンピュータも電子回路で構成されていますし、プログラムもメモリの中のON・OFFによって構成される記号の塊です。いわゆる機械語は電子回路のON・OFFによって表現されます。それが2進数であり、発展したものがニーモニック言語でありアセンブラ、16進数表記の考え方に発展し、それを構成するための高水準言語としてCやC++の言語が作られ、コンパイルやリンクの作業や翻訳・解析処理によって機械語を生成しているのです。
  
  
68行: 72行:
  
 
上記のような論理演算をプログラムで表現する場合には以下のようなものになります。
 
上記のような論理演算をプログラムで表現する場合には以下のようなものになります。
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
int main(){
 +
  bool bTrue = true;
 +
  bool bFalse = false;
 +
  bool bResult = false;
  
 +
  int nZero = 0;
 +
  int nOne = 1;
 +
  int nTwo = 2;
 +
  int nResult;
 +
 +
  printf("論理和\n");
 +
  bResult = bFalse || bFalse;
 +
  printf("%d = %d || %d\n",bResult, bFalse, bFalse);
 +
  bResult = bFalse || bTrue;
 +
  printf("%d = %d || %d\n",bResult, bFalse, bTrue);
 +
  bResult = bTrue || bFalse;
 +
  printf("%d = %d || %d\n",bResult, bTrue, bFalse);
 +
  bResult = bTrue || bTrue;
 +
  printf("%d = %d || %d\n",bResult, bTrue, bTrue);
 +
  printf("\n");
 +
 +
  printf("論理積\n");
 +
  bResult = bFalse && bFalse;
 +
  printf("%d = %d && %d\n",bResult, bFalse, bFalse);
 +
  bResult = bFalse && bTrue;
 +
  printf("%d = %d && %d\n",bResult, bFalse, bTrue);
 +
  bResult = bTrue && bFalse;
 +
  printf("%d = %d && %d\n",bResult, bTrue, bFalse);
 +
  bResult = bTrue && bTrue;
 +
  printf("%d = %d && %d\n",bResult, bTrue, bTrue);
 +
  printf("\n");
 +
 +
  printf("論理否定\n");
 +
  bResult = !bFalse;
 +
  printf("%d = !%d\n",bResult, bFalse);
 +
  bResult = !bTrue;
 +
  printf("%d = !%d\n",bResult, bTrue);
 +
  printf("\n");
 +
}
 +
</syntaxhighlight>
 
というように記述します。
 
というように記述します。
 +
 +
 +
上記のプログラムの結果はこうなります。
 +
<syntaxhighlight lang="text">
 +
論理和
 +
0 = 0 || 0
 +
1 = 0 || 1
 +
1 = 1 || 0
 +
1 = 1 || 1
 +
 +
論理積
 +
0 = 0 && 0
 +
0 = 0 && 1
 +
0 = 1 && 0
 +
1 = 1 && 1
 +
 +
論理否定
 +
1 = !0
 +
0 = !1
 +
 +
</syntaxhighlight>
  
  
78行: 144行:
  
  
if文における判定処理も論理演算の1(真=true)と0(偽=false)に基づいて実施されていますので、論理演算は重要な知識となります。よく理解しておきましょう。できれば一歩踏み込んだブール代数論やディジタル回路工学まで理解できると良いのですが、理解しようとすれば、時間がいくらあってもたりません。排他的論理和やAならばBといった集合論くらいは抑えておきたいものです。AND回路/OR回路/NAND回路/NOR回路/EXOR回路/**フリップフロップ回路/こういった仕組みを理解することによってコンピュータのクロックと演算処理装置と制御装置と入出力装置の仕組みが理解できるようになります。情報工学や情報技術系の勉強を体系的に理解する学問では学習する機会の多い学問分野になります。トランジスタや半導体のスイッチやメモリの仕組みについても理解していける学問です。半導体を理解するには、更に電子物性論といったものや力学や電磁気学や化学そしてさらには自然工学、光学を理解していくことになります。実際の製造ではもちろん統計学が必要になりますし、画像処理工学や技術者倫理学、各種機器の取り扱い資格に文献を理解する語学力も必要になってきます。コンピュータを構成する機器を理解するには医学とはまた異なる専門性がそこにはあるのかもしれません。コンピュータを軸にバイオミメティクスや医学、宇宙工学が展開しているとすれば情報工学の理解は基礎の基礎くらいなのかもしれないですね。もちろん知らなくても現代の専門家程度であれば継続的な研究は可能だと思いますが、これからの専門性は計算機に頼る部分も多大になっていくものではないかと思います。
+
ビット単位論理和の演算子は '''|''' です。<br />
 +
ビット単位論理積の演算子は '''&''' です。<br />
 +
ビット単位論理否定演算子は '''^''' です。
 +
 
 +
 
 +
プログラムのサンプルは以下のとおりです。2進数に変換する処理が標準関数では準備されていないので、テンプレート関数を使って変換出力する関数を作ってみました。誰がやっても大体同じような変換処理になると思います。なるべくわかりやすいように冗長なプログラムになっていますが、テンプレート関数が分からないと、変換関数もイマイチわからないと思います。テンプレート関数については別途記載したいとおもいますので、ここではビット単位の論理演算について理解してもらえればよいと思います。
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
template<class T>
 +
void printBit(T bit){
 +
  int nBitCnt;
 +
  int nBitScan;
 +
  char* pcharBitArr;
 +
  printf("(");
 +
  nBitCnt = sizeof(bit) * CHAR_BIT;
 +
  pcharBitArr = new char[nBitCnt];
 +
  nBitScan = 0;
 +
  while(nBitScan <= nBitCnt){
 +
    pcharBitArr[nBitScan] = bit & 1;
 +
    bit = bit >> 1;
 +
    nBitScan++;
 +
  }
 +
  nBitScan = nBitCnt;
 +
  while(nBitScan > 0){
 +
    if(nBitScan % 4 == 0 && nBitScan != nBitCnt){
 +
      printf(" ");
 +
    }
 +
    printf("%d",pcharBitArr[nBitScan - 1]);
 +
    nBitScan--;
 +
  }
 +
  printf(")B");
 +
 
 +
 
 +
 
 +
}
 +
int main(){
 +
  unsigned  lBitA = 0xFFFFFF00;
 +
  unsigned int  nBitB = 0xFF54;
 +
 
 +
  int nBitC = -65535;
 +
 
 +
  printf("A\n");
 +
  printf("0x%08X %014d:\n",lBitA,lBitA);
 +
  printBit(lBitA);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("B\n");
 +
  printf("0x%08X %014d:\n",nBitB,nBitB);
 +
  printBit(nBitB);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("C\n");
 +
  printf("0x%08X %014d:\n",nBitC,nBitC);
 +
  printBit(nBitC);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("ビット単位論理積\n");
 +
  printf("A & B\n");
 +
  printBit(lBitA);
 +
  printf(" and\n");
 +
  printBit(nBitB);
 +
  printf("\n");
 +
  printf("---------------------------------------------\n");
 +
  printBit(lBitA & nBitB);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("ビット単位論理和\n");
 +
  printf("A | B\n");
 +
  printBit(lBitA);
 +
  printf(" or\n");
 +
  printBit(nBitB);
 +
  printf("\n");
 +
  printf("---------------------------------------------\n");
 +
  printBit(lBitA | nBitB);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("ビット単位排他的論理和\n");
 +
  printf("A ^ B\n");
 +
  printBit(lBitA);
 +
  printf(" exor\n");
 +
  printBit(nBitB);
 +
  printf("\n");
 +
  printf("---------------------------------------------\n");
 +
  printBit(lBitA ^ nBitB);
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  printf("ビット単位論理否定\n");
 +
  printf("~B\n");
 +
  printBit(nBitB);
 +
  printf(" not\n");
 +
  printf("---------------------------------------------\n");
 +
  printBit(~nBitB);
 +
  printf("\n");
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
そして、処理結果はこのようになります。
 +
<syntaxhighlight lang="text">
 +
A
 +
0xFFFFFF00 -0000000000256:
 +
(1111 1111 1111 1111 1111 1111 0000 0000)B
 +
 
 +
B
 +
0x0000FF54 00000000065364:
 +
(0000 0000 0000 0000 1111 1111 0101 0100)B
 +
 
 +
C
 +
0xFFFF0001 -0000000065535:
 +
(1111 1111 1111 1111 0000 0000 0000 0001)B
 +
 
 +
ビット単位論理積
 +
A & B
 +
(1111 1111 1111 1111 1111 1111 0000 0000)B and
 +
(0000 0000 0000 0000 1111 1111 0101 0100)B
 +
---------------------------------------------
 +
(0000 0000 0000 0000 1111 1111 0000 0000)B
 +
 
 +
ビット単位論理和
 +
A | B
 +
(1111 1111 1111 1111 1111 1111 0000 0000)B or
 +
(0000 0000 0000 0000 1111 1111 0101 0100)B
 +
---------------------------------------------
 +
(1111 1111 1111 1111 1111 1111 0101 0100)B
 +
 
 +
ビット単位排他的論理和
 +
A ^ B
 +
(1111 1111 1111 1111 1111 1111 0000 0000)B exor
 +
(0000 0000 0000 0000 1111 1111 0101 0100)B
 +
---------------------------------------------
 +
(1111 1111 1111 1111 0000 0000 0101 0100)B
 +
 
 +
ビット単位論理否定
 +
~B
 +
(0000 0000 0000 0000 1111 1111 0101 0100)B not
 +
---------------------------------------------
 +
(1111 1111 1111 1111 0000 0000 1010 1011)B
 +
</syntaxhighlight>
 +
このように整数型intやlongで宣言された変数に代入した値は、2進数表記のような機械語で格納されていて、論理演算のビット毎論理演算では、結果表示のような演算がされます。10進数や16進数だけで演算結果を見ているとわけのわからない数字に変化する演算ですが、ビット単位でみるとすごく簡単な演算がなされてるのがわかると思います。対応するビット同士で論理積や論理和、排他論理和、論理否定を計算しているだけです。
 +
 
 +
 
 +
排他論理和はここではじめて登場する演算ですが、異なる数字同士のビット値ならば、1(真=true)とする変わった演算です。excrusive or とも表現されるためEX ORやEOR,XORと表現されます。XORが標準的な表現になると思います。
 +
{| style="color:black;" class="wikitable_ronriwa" border="1" cellspacing="0"
 +
|-
 +
! 値1 !! 値2 !! 結果
 +
|-
 +
| 0 || 0 || 0
 +
|-
 +
| 0 || 1 || 1
 +
|-
 +
| 1 || 0 || 1
 +
|-
 +
| 1 || 1 || 0
 +
|}
 +
異なるビットがあれば結果が1(真=true)になるため、ふたつの数値のビット単位排他的論理和でひとつでも1のビットがあれば同じ値でないということになります。ビット値の比較結果で間違っていた箇所はどこだったのかという計算をしたいときによく使われます。
 +
 
 +
 
 +
論理積の結果をよくみてみれば、FFFFFF00との論理積とれば上から48bit目までの値だけをもう一つの値から抜き出すような処理になっています。このようにビット演算は数値を取り出したり、比較したり、合わせたりという演算をすることができるので、ある大きさの機械語の1と0の並びにおいて何桁目かだけを1にしたりすることができるため、文字コードや数値コード以外の取り決めの中で通信するような機械語の規格のための操作として非常に重要な役割をもつ演算になっています。このような地道な論理演算の組み合わせでコンピュータおよび情報技術の全てが体現されていることに他ならないです。非常に複雑でち密な1と0のように表現される電気信号のON/OFFが羅列されて、そのネットワークや周辺機器の制御信号でのやりとりによって、人間にわかる形に変換する事をちょいちょいやりながらすべてが構成されているのですから、それらを制御するプログラムを理解し、開発し、カタチにすることは並大抵のことではないということがなんとなく実感できると思います。そして、それを少しでも制御してやろうという試みこそがプログラミングなのだと思います。わからないことだらけのコンピュータの超巨大で膨大な記号論を理解したり、数学的に表現したり、プログラムとして実現させるのですから、近代のコンピュータで何か役に立つものを作ろうとするとかなり膨大な処理をするプログラムを作っていることになります。もし簡単に便利なものがプログラムによって作れるのなら、それは開発環境が素晴らしいものであるからであり、プログラミング言語を機械語に翻訳してくれるシステムを構築してくれた先代の技術者達に感謝するべきところです。超巨大なビルが当然のように都市部の街中にたっていたりしますが、すべては小さなものから作り上げた基礎技術の上になりたっているのです。
 +
 
 +
 
 +
なんか、脱線してしまいましたが、話を少し戻しましょうか…
 +
 
 +
 
 +
if文における判定処理も論理演算の1(真=true)と0(偽=false)に基づいて実施されていますので、論理演算は重要な知識となります。よく理解しておきましょう。できれば一歩踏み込んだブール代数論やディジタル回路工学まで理解できると良いのですが、理解しようとすれば、時間がいくらあってもたりません。排他的論理和やAならばBといった集合論くらいは抑えておきたいものです。AND回路/OR回路/NAND回路/NOR回路/EXOR回路/**フリップフロップ回路/こういった仕組みを理解することによってコンピュータのクロックと演算処理装置と制御装置と入出力装置の仕組みが理解できるようになります。情報工学や情報技術系の勉強を体系的に理解する学問では学習する機会の多い学問分野になります。トランジスタや半導体のスイッチやメモリの仕組みについても理解していける学問です。半導体を理解するには、更に電子物性論といったものや力学や電磁気学や化学そしてさらには自然工学、光学、量子化学、量子力学、量子物理学を理解していくことになります。実際の製造ではもちろん統計学が必要になりますし、画像処理工学や技術者倫理学、各種機器の取り扱い資格に文献を理解する語学力も必要になってきます。コンピュータを構成する機器を理解するには医学とはまた異なる専門性がそこにはあるのかもしれません。コンピュータを軸にバイオミメティクスや医学、宇宙工学が展開しているとすれば情報工学の理解は基礎の基礎くらいなのかもしれないですね。もちろん知らなくても現代の専門家程度であれば継続的な研究は可能だと思いますが、これからの専門性は計算機に頼る部分も多大になっていくものではないかと思います。
 +
 
 +
 
 +
[[C PlusPlus#Cにもあった技術|C++]]へ戻る

2017年5月29日 (月) 00:00時点における最新版



個人用ツール
名前空間

変種
操作
案内
ツールボックス