複素数の対数の写像について

初稿 2021年11月06日
修正 2025年2月13日
# はじめに
　プログラムでlog(-1)と書くと、NaN(非数)が返されます。自分のプログラムでは、０のように扱われていたので、このことに無頓着であまり気にしていませんでした。よくよく調べると、log(-1)は実数では存在せず、虚数なら存在するということを知ったので、いろいろ試した結果のまとめです。

# オイラーの公式
```math 
e^{iθ} = \cos\theta + i\sin\theta
```
から
```math 
e^{i\pi} = -1
```
となり、
両辺の対数をとって
```math
\log(-1)=\log(e^{i\pi})=i\pi
```
が得られます。
負数の対数は、虚数となることが確認できます。

# google
　googleの検索ボックスに「ln(-1)」もしくは「log(-1)/log(e)」と入力すると「3.14159265 i」と答えが返ってくることからgoogleは複素数を扱えます。
 ※googleのlogは底が10なので、式変形して使うか、底がeのlnを使います。

# 多価関数
負数の対数は以下の法則があります。
```math
\log(-1)=i\pi
```
```math
\log(-2)=\log(2)+i\pi
```
```math
\log(-3)=\log(3)+i\pi
```
正確には、
```math
\log(-a)=\log(a)+i\pi(1+2n)
```
で、多価関数と呼ばれます。
arcsinθが多値を持つことと、同じです。
※リーマン面も面白い形。

# log(z)　複素数の対数
　プログラムで、複素数を扱うのに、pythonが便利そうなので、環境を整えます。
pythonは初めてなので、googleのcolabから使い始めましたが、すぐに限界が来たので、やめました。オフライン実行環境を探しましたが、最終的に、processing.pyに行きつきました。
　複素数ライブラリcmathには、複素数の関数も用意されており、logに複素数を渡せることに気がつきました。前の疑問に立ち戻り、どんな複素数を対数に渡せば、どんな複素数になるか、という疑問を解決させます。つまり、どんな写像になっているかという疑問です。

# 環境
Processing.py(3063)
math, cmathライブラリ

# 結果
グリッド間隔は１です。
(-1-1i)〜(1+1i)の範囲の複素数が、どこに写像されるかを示した図です。
色々な範囲で試した結果、πiよりも大きくなることはなく、-πiよりも小さくなることはありませんでした。arcsinのように(-π<θ<π)で返されるのだと思います。というわけで、写像の図としては、上下にも永遠に繋がっていると言えます。
また、元の複素数の範囲を変えると、実軸方向に全体的にスライドしました。
魚の鱗のような、イメージでしょうか。ちょっとずつズレながら、全体を埋めるような。
![256z.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/9c6917a6-e4a1-ec4d-878b-1567b69b3035.png)
![256_z.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/caf78cc2-4e8b-a9a8-0d10-a04945626907.png)
![256z2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/8f28538d-55e9-214c-2fbd-5605e13166d6.png)
![256_z2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/c14f3244-af16-9ae1-d1aa-fe665bbfde3d.png)


# コード

```py:py_complex_log.pyde
import math
import cmath

size(512, 512)
background(255)

z = 0 + 1j
# z -= 1j
print(z)
print(cmath.log(z))

translate(width / 2, height / 2)
scale(50)
strokeWeight(1 / 50.0)

# grid
stroke(200)
for x in range(-5, 6):
    line(x, -height, x, height)
for y in range(-5, 6):
    line(-width, y, width, y)

#######
strokeWeight(1 / 25.0)
colorMode(HSB,360,100,100)
for y in range(256):
    for x in range(256):
        re = map(x, 0, 256, -1, 1)
        im = map(y, 0, 256, -1, 1)
        if re == 0 and im == 0:
            break
        z = complex(re, im)
        th = math.degrees(cmath.phase(z)+PI)
        _z = cmath.log(z)
        stroke(th, 100, 100)
        point(_z.real, _z.imag)
```

# sqrt平方根の写像
同様に、平方根についても確認しました。
√-1 = i
√i = √2/2+√2/2i
√4i = √2+√2i
√(1+i) = 1.09868411347+0.455089860562i

グリッド間隔は１です。
(-1-1i)〜(1+1i)の範囲の複素数が、どこに写像されるかを示した図です。
曲座標っぽくなる
![sqrt1024_z1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/ea24ebe8-d8d5-3281-4660-a3ef76c9b562.png)

(-4-4i)〜(4+4i)の範囲の複素数が、どこに写像されるかを示した図です。
4倍にすると、2倍になりました。
![sqrt1024_z4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/6181e119-1f92-5325-5659-1a74ac6553d5.png)

# コード

```py:py_complex_sqrt.pyde
import math
import cmath

size(512, 512)
background(255)

z = 0 + 1j
# z -= 1j
print(z)
print(cmath.sqrt(z))

translate(width / 2, height / 2)
scale(100)
strokeWeight(1 / 100.0)

# grid
stroke(200)
for x in range(-5, 6):
    line(x, -height, x, height)
for y in range(-5, 6):
    line(-width, y, width, y)

#######
strokeWeight(1 / 100.0)
colorMode(HSB,360,100,100)
for y in range(1024):
    for x in range(1024):
        re = map(x, 0, 1024, -1, 1)
        im = map(y, 0, 1024, -1, 1)
        if re == 0 and im == 0:
            break
        z = complex(re, im)
        th = math.degrees(cmath.phase(z)+PI)
        _z = cmath.sqrt(z)
        stroke(th, 100, 100)
        point(_z.real, _z.imag)
```