Javaでオイラーの公式を表現してみたかったけど...

f:id:ts0818:20190831151903j:plain

Java複素数とかの表現もできるみたいですね~。

www.j-lab.tech

codezine.jp

⇧  上記サイト様によると、

マンデルブロー集合はフラクタル図形の一種として有名で、これを描画する方法は広く知られています。

ポーランド生まれの数学者Benoit B. Mandelbrotが、1982年に出版した『The Fractal Geometry of Nature』で紹介してから、急に有名になりました。

マンデルブロー集合による新しいフラクタル図形を探索する (1/2):CodeZine(コードジン)

と説明されています。詳しくは、上記サイト様をチェケラ~!

 

だが、しかし!今回は、オイラーの公式について調べてみました。

taketo1024.hateblo.jp

⇧  上記サイト様を参考にさせていただきました。 

 

オイラーの公式 とは?

今日も、Wikipediaさんに聞いてみた。

数学、特に複素解析におけるオイラーの公式オイラーのこうしき、Euler's formula)は、指数関数三角関数の間に成り立つ以下の関係をいう。

ここで e· は指数関数、i は虚数単位cos ·, sin · はそれぞれ余弦関数および正弦関数である。

オイラーの公式 - Wikipedia

とあり、

任意の複素数 θ に対して成り立つ等式であるが、特に θ が実数である場合が重要でありよく使われる。θ が実数のとき、θ は複素数 e がなす複素平面上の偏角(角度 θの単位はラジアン)に対応する。

オイラーの公式 - Wikipedia

であると...

いや、サッパリ分からんけど...。

オイラーの公式は、紆余曲折があったようで、

公式の名前は18世紀の数学者レオンハルト・オイラー (Leonhard Euler) に因むが、最初の発見者はロジャー・コーツ (Roger Cotes) とされる。コーツは1714年

を発見したが、三角関数の周期性による対数関数の多価性を見逃した。

オイラーの公式 - Wikipedia

⇧  最初の発見者は、ロジャー・コーツって人だったようです。

ですが、いまの公式の形に持っていったのが、オイラーということで、

1740年頃オイラーはこの対数関数の形での公式から現在オイラーの公式の名で呼ばれる指数関数での形に注意を向けた。指数関数と三角関数級数展開を比較することによる証明が得られ出版されたのは1748年のことだった

オイラーの公式 - Wikipedia

オイラーの公式 と呼ばれるようになったそうな。

この公式は複素解析をはじめとする純粋数学の様々な分野や、電気工学物理学などで現れる微分方程式の解析において重要な役割を演じる。物理学者のリチャード・ファインマンはこの公式を評して「我々の至宝」かつ「すべての数学のなかでもっとも素晴らしい公式」だと述べている。

オイラーの公式 - Wikipedia

⇧ 大絶賛 されとりますな。

 

オイラーの公式は、変数 θ が実数である場合には、右辺は実空間上で定義される通常の三角関数で表され、虚数の指数関数の実部と虚部がそれぞれ角度 θ に対応する余弦関数 cos と正弦関数 sin に等しいことを表す。このとき、偏角 θ をパラメータとする曲線 e は、複素平面上の単位円をなす。 特に、θ = π のとき(すなわち偏角が 180 度のとき)、

となる。この関係はオイラーの等式 (Euler's identity) と呼ばれる。

オイラーの公式 - Wikipedia

θ が純虚数である場合には、左辺は実空間上で定義される通常の指数関数であり、右辺は純虚数に対する三角関数となる。

オイラーの公式は、三角関数 cos θ, sin θ が双曲線関数 cosh(), sinh()/i に対応することを導く。また応用上は、オイラーの公式を経由して三角関数を複素指数関数に置き換えることで、微分方程式フーリエ級数などの扱いを簡単にすることなどに利用される。

オイラーの公式 - Wikipedia

⇧  サッパリですな... そう!、サッパリ分からんのだよっ!

 

www.gachitan.com

⇧  上記サイト様が、解説してくれています。

Wikipediaさんが言うように、「 θ が実数である場合」であれば、

⇧  上記サイト様の図にあるように、螺旋 の軌道になるであろうと。

おそらく、こういう平面を、

f:id:ts0818:20190831163958p:plain

並べているんでしょうね。

f:id:ts0818:20190831163736p:plain

⇧  緑の矢印が、微分積分でいうところの、t みたいなものですかね。

それぞれの座標を繋げていくと、螺旋になるってことであろうと。本来なら数えきれないぐらい並べているのではないかと。じゃないと、きれいな螺旋にならんと思うし。

まぁ、なんとなくなザックリしたイメージだけは分かったということで。
 

 

Javaオイラーの公式を実装してみる

ということで、いざ、実装。

をプログラミングで表すわけなんですが、虚数 i をどう実装すれば良いのか...

複素数で表現するらしい。

数学における複素数(ふくそすう、complex number)は、実数の対 ab と 1 と線型独立な(実数ではない)要素 i の線型結合 a + bi の形に表される二元数: 実数体上の二次拡大環の元)で、基底元 i はその平方が −1 になるという特別な性質を持ち虚数単位と呼ばれる

複素数 - Wikipedia

つまり、虚数、単独での表現というのは難しいというのか、できない?らしい。つまり、i を求めようとすると、a + bi というセットで考えないと駄目ってことなんですかね? 

で、残念ながら、Java の標準の API では、複素数を扱うものがいまのところ無いらしい。(将来的に、Javaの標準APIとして導入されないのかな?)

wasan.hatenablog.com

⇧  上記サイト様によりますと、Apache Commons のライブラリには、複素数を扱うAPI が存在するらしい。

Apache Commons Math(アパッチ・コモンズ・マス)は、ApacheのトッププロジェクトであるApache CommonsにあるApache Commons#Commons Properに属する自己完結した数学と統計学の軽量コンポーネントである。 統計解析、複素数演算、分数演算、行列演算、固有値問題QR法数値積分多変量解析差分法などのライブラリを持つ。

 

Apache Commons Math - Wikipedia

⇧  おそらく、これの、複素数演算ってライブラリで実現できるってことかしら?

オライリー複素数っぽいものを公開してくれてたっぽいですが、作成されたのが、1997年...時代を感じさせてくれます。

resources.oreilly.com

ちなみに、オライリーソースコードはこんな感じ。

// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com)
// Copyright (c) 1997 by David Flanagan
// This example is provided WITHOUT ANY WARRANTY either expressed or implied.
// You may study, use, modify, and distribute it for non-commercial purposes.
// For any commercial use, see http://www.davidflanagan.com/javaexamples

/**
 * This class represents complex numbers, and defines methods for performing
 * arithmetic on complex numbers.
 **/
public class ComplexNumber {
  // These are the instance variables.  Each ComplexNumber object holds
  // two double values, known as x and y.  They are private, so they are
  // not accessible from outside this class.  Instead, they are available 
  // through the real() and imaginary() methods below.
  private double x, y;

  /** This is the constructor.  It initializes the x and y variables */
  public ComplexNumber(double real, double imaginary) {
    this.x = real;
    this.y = imaginary;
  }

  /** 
   * An accessor method.  Returns the real part of the complex number.
   * Note that there is no setReal() method to set the real part.  This means
   * that the ComplexNumber class is "immutable".
   **/
  public double real() { return x; }

  /** An accessor method.  Returns the imaginary part of the complex number */
  public double imaginary() { return y; }

  /** Compute the magnitude of a complex number */
  public double magnitude() { return Math.sqrt(x*x + y*y); }

  /** 
   * This method converts a ComplexNumber to a string.  This is a method of
   * Object that we override so that complex numbers can be meaningfully
   * converted to strings, and so they can conveniently be printed out with
   * System.out.println() and related methods
   **/
  public String toString() { return "{" + x + "," + y + "}"; }

  /** 
   * This is a static class method.  It takes two complex numbers, adds them, 
   * and returns the result as a third number.  Because it is static, there is
   * no "current instance" or "this" object.  Use it like this:
   * ComplexNumber c = ComplexNumber.add(a, b);
   **/
  public static ComplexNumber add(ComplexNumber a, ComplexNumber b) {
    return new ComplexNumber(a.x + b.x, a.y + b.y);
  }

  /**
   * This is a non-static instance method by the same name.  It adds the
   * specified complex number to the current complex number.  Use it like this:
   * ComplexNumber c = a.add(b);
   **/
  public ComplexNumber add(ComplexNumber a) {
    return new ComplexNumber(this.x + a.x, this.y+a.y);
  }

  /** A static class method to multiply complex numbers */
  public static ComplexNumber multiply(ComplexNumber a, ComplexNumber b) {
    return new ComplexNumber(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
  }

  /** An instance method to multiply complex numbers */
  public ComplexNumber multiply(ComplexNumber a) {
    return new ComplexNumber(x*a.x - y*a.y, x*a.y + y*a.x);
  }
}

というわけで...って、まったく、虚数 i についての記述が見られんのだが...駄目じゃないの、これ...

写経チックに記述してみましたが...

f:id:ts0818:20190831231958p:plain

/TestEuler/src/main/TestComplexNumber.java

package util;

public class ComplexNumber {
  private double real, imaginary;

  public ComplexNumber() {

  }

  public ComplexNumber(double real, double imaginary) {
    this.real = real;
    this.imaginary = imaginary;
  }

  public double getReal() {
    return (real);
  }

  public void setReal(double real) {
    this.real = real;
  }

  public double getImaginary() {
    return (imaginary);
  }

  public void setImaginary(double imaginary) {
    this.imaginary = imaginary;
  }

  public ComplexNumber multiply(ComplexNumber factor) {
    ComplexNumber product = new ComplexNumber();

    product.setReal((real * factor.real) - (imaginary * factor.imaginary));
    product.setImaginary((imaginary * factor.real) + (real * factor.imaginary));
    return (product);
  }

  public ComplexNumber divide(ComplexNumber divisor) {
    ComplexNumber quotient = new ComplexNumber();

    quotient.setReal(((real * divisor.real) + (imaginary * divisor.imaginary))
        / (double) (Math.pow(divisor.real, 2) + Math.pow(divisor.imaginary, 2)));
    quotient.setImaginary(((imaginary * divisor.real) - (real * divisor.imaginary))
        / (double) (Math.pow(divisor.real, 2) + Math.pow(divisor.imaginary, 2)));
    return (quotient);
  }
}

/TestEuler/src/util/ComplexNumber.java

package main;

import util.ComplexNumber;

public class TestComplexNumber {

  public static void main(String[] args) {
    // 
    double theta = Math.PI / (double)2;
    System.out.println("cos: " + Math.cos(theta));
    System.out.println("sin: " + Math.sin(theta));
    ComplexNumber ei = new ComplexNumber(Math.cos(theta), Math.sin(theta));
    System.out.println(ei.getReal() + " + " +  ei.getImaginary());
    
  }
}

 んで実行してみる。

f:id:ts0818:20190831232434p:plain

f:id:ts0818:20190831232400p:plain

う、う~ん...駄目っすね

って表現できていない気がする。

情報が無いからよく分からん...やっぱり理系じゃないとキツイかな...

モヤモヤ感しか残らなかったけど、疲れたので、今回はこのへんで。

2019年9月3日(火)追記:↓  ここから

frost さんにコメントをいただき、

は表現できていたようです。frost さん、ありがとうございます。

2019年9月3日(火)追記:↑  ここまで