2016年06月26日

演算子の多重定義

今日はそれほど暑くもなく、カラッとしたいい天気でした。しかし、明日からまた雨のようですね。

C++ には「演算子の多重定義」というものがあります。任意の型に対して、int 型や double 型などと同等に演算子が利用できるというものです。

SomeClass SomeClass::operator+( const SomeClass& s1, const SomeClass& s2 );

という関数を実装すれば、

SomeClass s1, s2;
:
// 何らかの方法で値を代入
:
SomeClass add = s1 + s2;

と書くことができます。四則演算だけではなく、等号・不等号演算子やポインタ・参照演算子なども多重定義できるので、うまく利用すれば非常に便利な反面、やみくもに使うと混乱の元とも言われています。例えば、ベクトルに対して積の演算子を多重定義した場合、それは内積なのか外積なのかというのは利用する場面によって変わります。こんなときは素直に innerproduct, outerproduct と通常の関数を用意したほうが混乱しなくて済みます。

演算子の多重定義の実体は関数やメンバ関数です。そうなると、演算子の優先順位はどうなるのかが気になるところです。簡単なサンプルを作ってテストしてみました。

/// 10 を法とした合同算
struct Mod10
{
  unsigned int r; // 10 を法としたときの値

  // コンストラクタ
  Mod10() : r( 0 ) {}

  // 積の代入演算子の多重定義
  Mod10& operator*=( const Mod10& i )
  {
    r = ( r * i.r ) % 10;
    return( *this );
  }

  // 和の代入演算子の多重定義
  Mod10& operator+=( const Mod10& i )
  {
    r = ( r + i.r ) % 10;
    return( *this );
  }
};

// 積の演算子の多重定義
Mod10 operator*( const Mod10& i1, const Mod10& i2 )
{
  Mod10 buff( i1 );
  buff *= i2;

  return( buff );
}

// 和の演算子の多重定義
Mod10 operator+( const Mod10& i1, const Mod10& i2 )
{
  Mod10 buff( i1 );
  buff += i2;

  return( buff );
}

int main( int argc, char* argv[] )
{
  if ( argc < 3 ) return( -1 );

  unsigned int i = atoi( argv[1] );
  unsigned int j = atoi( argv[2] );

  Mod10 m1; m1.r = i;
  Mod10 m2; m2.r = j;

  Mod10 ans1 = m2 * m1 + m1;
  Mod10 ans2 = m1 + m1 * m2;
  Mod10 ans3 = ( m1 + m1 ) * m2;

  std::cout << ans1.r << std::endl;
  std::cout << ans2.r << std::endl;
  std::cout << ans3.r << std::endl;
}

演算子の優先順位を考慮していなければ、関数に置き換えると

Mod10 ans1 = operator*( m2, operator+( m1, m1 ) );
Mod10 ans2 = operator+( m1, operator*( m1, m2 ) );

Mod10 ans1 = operator+( operator*( m2, m1 ), m1 );
Mod10 ans2 = operator*( operator+( m1, m1 ), m2 );

となって、ans1 と ans2 の値は異なるのではないかと予想していましたが、例えば m1 = 2, m2 = 3 とすると、

8
8
2

となってちゃんと優先順位が考慮されていました。で、「プログラミング言語 C++」を調べてみたら、最初の方に「優先順位を考慮している」ときちんと記述されていました。それにしても、今まで何回か使ったことがあるのに疑問に思わなかったというのが少々情けない。。。  

2016年06月19日

ピカ・パウ

昨日は、いっしょに演奏しているグループのメンバーと静岡に遊びに行ってました。

沼津で海鮮づくしのあと、三島市にある「ピカ・パウ」という店で他のグループの方といっしょに夕食 + 演奏で楽しんできました。昼間は異常な暑さでしたが、駿河湾のクルージングで外洋に出ると結構涼しい風が吹いていて心地よかったです。
ピカ・パウは南米料理の専門店。昼間の海鮮づくしでお腹が空いておらずあまり食べられませんでしたが、料理はおいしかったですよ。大半はビール飲みながら演奏してたので、今度は食事目当てで行ってみたいです。

ピカ・パウ ( Pica Pau ) の意味を調べてみましたが、Google 翻訳はダメでした。ググってみるとアニメの Woodpecker がでてくるので、キツツキを意味するんでしょうかね?

数学問題 bot」さんから、東大の出題問題です。合っている保証はありません。

-----

10進法で表して5桁以上の平方数に対し、1000の位の数、100の位の数、10の位の数、および1の位の数の4つ全てが同じ数となるならば、その平方数は10000で割り切れることを示せ。 ( 04 東大理系 )

1000 の位までの数が決まるのは、元の数の 2 桁分のみです。なぜなら、3 桁目は 100n で表せるので、平方すれば 10000n2 で、下 4 桁に影響しないからです。従って、01 ~ 99 の中で、平方して 4 桁が等しくなるような数が存在しなければ、ゼロ以外に条件を満たす数は存在しないことになります。
平方数の下一桁は、1 の位の数の平方の下一桁のみで決まるので、1, 4, 5, 6, 9 のいずれかしかありません。よって、平方して 4 つの数が同じになる場合は 1111, 4444, 5555, 6666, 9999 の 5 つに絞られます。

1111 = 11 x 101 なので、これは成り立ちません。同様に

4444 = 22 x 11 x 101
5555 = 5 x 11 x 101
6666 = 2 x 3 x 11 x 101
9999 = 32 x 11 x 101

であり、いずれも平方数にはならないので、ゼロ以外に条件を満たす数は存在せず、平方数は必ず 10000 で割り切れることが証明されました。  

Posted by fussy at 20:08Comments(0)TrackBack(0)数学

2016年06月12日

ちょっと一息

名古屋も夕方から雨が降ってきました。明日は一日中ずっと雨のようですね。

「アルゴリズムのコーナー」を更新しました。テーマは「主成分回帰 ( PCR ) と部分最小二乗法 ( PLS )」です。かなり前から取り上げたかったテーマの一つで、ある程度まで理解するのに結局一年くらいかかりました(放置していたと言った方がいいかも)。まだ、完全に理解したとは言えない状態ですが、ある程度まとめることができたので公開しました。

次のテーマの候補もいくつかありますが、ちょっと息切れ状態です。回復してからまた作業を進めようかと思っています。止めるつもりはないので、回復すればまた始めるつもりです(リハビリを兼ねて昔のページの更新をするかもしれません)。  

Posted by fussy at 18:33Comments(0)TrackBack(0)

2016年06月05日

Xubuntu 切り替え完了

Xubuntu への切り替えが完了しました。

まだ少し変更したい箇所がありますが、とりあえずは満足できる状態となりました。前の環境は念のため残してはあるものの完全に止めてあります。それにしても思ったより早く移行ができました。
困ったことに、Virtualbox を Window モードにすると自動的に画面の大きさが変えられてしまいます。Window モードでも問題なく使えればいいのですが、マウスのクリック位置がずれてしまうようでマウスでのクリックや範囲選択で困った状態になります。Vine のときはそんなことはなかったのですが、自動リサイズを OFF にしても修正されないので今のところはあきらめて常にフルスクリーンモードで作業しています。
もう一点は、時々日本語入力 ( Mozc ) が頻繁に ON / OFF する状態になることです。これは以前から問題があってその対処法も知っているのですが、対処したはずなのになぜか時々この状態が発生することがあります。あまり頻繁に起こるなら少々問題ですね。

しかし、一番懸念していたソースのコンパイルは、ほとんど修正せずに ( gtk+ を利用している箇所が少し厄介でしたが ) 通ってしまったのはうれしいことです。次回のテーマ用のサンプル・プログラムも本日ある程度完成しましたので、勢いで近日中に仕上げたいと考えています。  続きを読む

Posted by fussy at 20:08Comments(0)TrackBack(0)

2016年06月04日

梅雨入り

とうとう、梅雨入り宣言されました。

来週は晴れの日はほとんどないようです。しかし、大雨にならなければそれほど苦にもならないというものです。ゲリラ豪雨だけはかんべんしてほしいですね。

数学問題bot」さんから今回は京大の問題。解き方を気付いた後は割と簡単に解けました。気付くまでが大変ですが。
例によって合っている保証なしです。

-----

2 以上の自然数 n に対し、n と n2 + 2 がともに素数になるのは n = 3 の場合に限ることを示せ。( 06 京都前期・理 )

全ての自然数は、k ≥ 0 として 3k, 3k + 1, 3k + 2 で表すことができます。3k は k & gt; 1 のとき合成数なので、n = 3k + 1, 3k + 2 として n2 + 2 を計算すると

( 3k + 1 )2 + 2 = 9k2 + 6k + 3 = 3( 3k2 + 2k + 1 )

( 3k + 2 )2 + 2 = 9k2 + 12k + 6 = 3( 3k2 + 4k + 2 )

で必ず 3 の倍数になります。従って、n と n2 + 2 が n = 3 以外でともに素数となることはありません。
  

Posted by fussy at 22:37Comments(0)TrackBack(0)数学