はじめMath! Javaでコンピュータ数学

第39回行列の数学 ベクトルのスカラ倍と乗算

のこぎりを使い始めた小学生の頃は、2cm角の角材一本切るのにも苦労しました。押す、引くの感覚がよく分りませんから、闇雲にごしごしと動かして、すぐに疲れてしまいました。まるで魔法のようにあっという間に板や棒を切断する父親と、自分の違いに歯がゆく思ったものです。今では私も角材数本を縛ってまとめて4本切ったりします。経験が積み重なると、要領良い方法を自然と思いつくものです。また、要領よくしないと仕事として成り立ちません。

しかし、下手に効率を良くしようとすると、かえって結果は芳しくありません。専門家、プロと呼ばれる人々は、仕事をいかに要領よく、かつ抜かりなく行うことが出来るかを追求した人たちだと言えます。

現在学んでいる行列の数学は、単純計算を、いかに効率よく抜かりなく行うことが出来るかを追求したものです。更にそれをコンピュータに行わせることが出来れば大変な省力化につながります。今回もシンプルな内容です。

初めてのこぎりを手にした時のような初心に返って、取り組んでみてください。

図39.1 プロの仕事は要領よく抜かりなく
図39.1 プロの仕事は要領よく抜かりなく

ベクトルのスカラ倍

スカラ倍とは、定数倍のことです。具体的には、2倍や3倍にするということです。ベクトルに掛けられた定数値をベクトルの全ての成分に掛け合わせます。

ベクトルのスカラ倍の一般的な形を紹介します。ベクトルAのスカラ倍を式39.2であらわしています。

ベクトルのスカラ倍には、数値同士の乗算と同じように、交換法則や結合法則が成り立ちます。表39.1にベクトルのスカラ倍に関する法則一覧を掲載します。

表39.1 ベクトルのスカラ倍演算法則一覧
法則名演算の例
交換法則cA=Ac
結合法則c(dA)=cdA
分配法則(c+d)A=cA+dA
c(A+B)=cA+cB

ベクトルのスカラ倍の具体例

お年玉のポチ袋に10円玉を5枚、100円玉を3枚入れたとしましょう[1]⁠。このポチ袋に入っている硬貨の枚数をベクトルで表すと、次のように書くことが出来ます。

今日は親戚の子供達が7人[2]やってくるとします。するとポチ袋が7枚必要です。中身も同じでないと、けんかの種になってしまいます。さて、それぞれの硬貨を何枚用意しなければならないでしょうか。

それぞれの硬貨が何枚必要か、計算する式は、ベクトルを利用すると次のようにシンプルに書けます。

10円玉は35枚、100円玉は21枚必要だとわかりました。

ベクトルには、計算式を大変シンプルに記述できる利点があります。この考え方をプログラミングに利用すれば、集計・統計処理に大きな力を発揮しそうなことが予想できるでしょう。

ベクトルの乗算

ベクトル同士を掛け合わせることをベクトルの乗算といいます。乗算の結果はベクトルではなくスカラ値(定数値)になります。

以下にベクトルの乗算の一般的な形を紹介します。

ベクトルの乗算の具体例

ベクトルを掛け合わせるとスカラ値になる、というのは、具体的にどんな場合が例に挙げられるでしょうか。

それを考えるために、先ずベクトルの乗算がどのように行われるか見ておきましょう。ベクトルの乗算の前提条件は、次元が同じことです。次元が異なるベクトル同士の乗算は出来ません。

次のような具体例が考えられますよ。式39.8のベクトルAはあるスーパーで販売する商品の単価を表すとします。たとえば、しその葉1枚3円、たくあん1切れ5円といった具合です。式39.9のベクトルBは1パックに納めるしその葉とたくあんの数を表すとしましょう。今回のパックには、しその葉2枚、たくあんが4切れ入るということです。この商品ひとパックの値段は、式39.11のように、ベクトルの乗算を行うことで計算できます。

大変単純な計算ですが、品数が増えた場合はどうでしょうか?スーパーでは膨大な数の商品を取り扱いますよね。商品の売り上げのうちの、消費税分はいくらになるだろう、なんて計算は単純そうですが、数が多くなると大変です。そんなときこそ、コンピュータの出番です。データを入力し、計算方法を指示すれば、コンピュータは文句を言わず計算をしてくれます。

問題:ベクトルのスカラ倍、ベクトル同士の乗算を行う関数を作りましょう。

ベクトルのスカラ倍は整数の配列を、ベクトル同士の乗算は整数のArrayListを用いてください。次元数はあらかじめわからないものとします。

乗算では、引数として渡されたベクトルの次元が異なる場合、エラーメッセージを表示して強制終了させましょう。

(1)ベクトルをスカラ倍する関数を作りましょう。数値は整数、ベクトルには配列を用いて下さい。

(2)ベクトル同士を乗算する関数を作りましょう。数値は整数、ベクトルにはArrayListを用いて下さい。

解説

(1)ベクトルをスカラ倍する関数を作りましょう。数値は整数、ベクトルには配列を用いて下さい。

解答例を示します。これまでの問題をこなされた方にとっては、特に難しいと感じるところはなかったでしょう。int型の整数を用いていますから、スカラ倍も乗算もオーバーフローを起こすかどうかを計算前に判断する仕組みを入れるとより実用的でしょう。発展課題として取り組んでみてはいかがでしょうか。

ソースコード:HairetsuDeMatrixScalar.java
//サンプルコード
//ベクトルのスカラ倍 配列版
//filename : HairetsuDeMatrixScalar.java

class HairetsuDeMatrixScalar {

  static final int SCALAR = 5;

  public static void main(String[] args) {

    int a[] = {1,2,3,5,8}; //ベクトルA
    int b[] = new int[a.length]; //ベクトルB(ベクトルAと同次元)
    // B = cA
    vScalarMatrix(a,SCALAR,b);
    //結果表示
    for( int i = 0 ; i < a.length ; ++i ){
      System.out.println(SCALAR + " * a["+i+"] = b["+i+"] => " +
       SCALAR + " * " + a[i] + " = " + b[i]);
    }
  }// end of main


  /**
   * vScalarMatrix(A,c,B)
   * ベクトルA のスカラ倍cA をベクトルB にセットする
   */
  static void vScalarMatrix(int a[], int c , int b[]){
    if (a.length == b.length){
      //加算可能
      for( int i = 0; i < a.length ; i++){
        b[i] = c * a[i];
      }
    } else {
      System.out.println("戻り値用の配列長が適切ではありません。");
      System.exit(0);
    }
  }
}// end of this class

(2)ベクトル同士を乗算する関数を作りましょう。数値は整数、ベクトルにはArrayListを用いて下さい。

ArrayListはサイズを動的に変更できるのですが、今回の問題の意図では自由な操作は出来ません。関数に与えられたリストのサイズが同じ場合にのみ計算を実行するようチェックが必要です。

ソースコード:ArrayListDeMatrixMultiplication.java
//サンプルコード
//ベクトルの積をとる。ArrayList 版。
//filename : ArrayListDeMatrixMultiplication.java

import java.util.ArrayList;

class ArrayListDeMatrixMultiplication {

  public static void main(String[] args) {

    //ベクトルA の宣言と初期化
    ArrayList<Integer> A = new ArrayList<Integer>();
    int a[] = {1,2,3,5,8};
    for (int i=0 ; i < a.length ; ++i ) A.add( a[i] );
    //ベクトルB の宣言と初期化
    ArrayList<Integer> B = new ArrayList<Integer>();
   int b[] = {2,4,5,7,9};
//   int b[] = {2,5}; //次元数が異なる場合は加算できない
    for (int i=0 ; i < b.length ; ++i ) B.add( b[i] );
    //積の値を格納するc の宣言
    int c = 0;
    int test = 0;

    //c = A * B
    c = aMultiMatrix(A,B);
    //結果と確認の表示
    for( int i=0 ; i < A.size() ; ++i ){
      test += A.get(i) * B.get(i);
      System.out.print("A("+i+") * B("+i+") = ");
      System.out.println(A.get(i)+" * "+B.get(i)
                          + " : test = " + test);
    }
    System.out.println("c = " + c + " : test = " + test);
  }// end of main
  /**
   * vMultiMatrix(A,B)
   * ベクトルA とベクトルB の積を返す
   */
  static int aMultiMatrix(ArrayList<Integer> A,
                           ArrayList<Integer> B){
    int sum = 0;
    if (A.size() == B.size()){
      //乗算可能
      for( int i = 0; i < A.size() ; i++){
        sum += A.get(i) * B.get(i) ;
      }
    } else {
      //乗算不能
      System.out.println("乗算できません");
      System.exit(0);
    }
    return sum;
  }

}// end of this class

今回はここまで

問題をうまくコードに出来たでしょうか。前回とほぼ同様のコードで処理できたことでしょう。次回からは行、列ともに複数の一般的な行列の取り扱いを始めます。行列の数学もいよいよ本番です。気合いを入れていきましょう。・おや、加算、減算、乗算・除算は?と思われた方、勘が鋭い。

行列の除算はちょっと特別なんです。しばらく先で学習しますので、今のところは置いておいてください。行列の数学の道は、まだまだ長いのです。

おすすめ記事

記事・ニュース一覧