70337
Mは操作量を表します。  
添字の１は一回前の操作であることを表します。

これを実行すると比例ゲインKp＝0.8の時にオフセットなしでゴールまで達するので違和感です。比例制御はその仕組みのせいで必ずオフセットを生じるはずです…

```

    import numpy as np
    from matplotlib import pyplot as plt 
    from numpy.random import *
    
    goal=90
    M1=0.00 
    
    Kp=0.1
    
    t_list=[]
    M_list=[]
    t=50
    t_list.append(0)
    M_list.append(0.00)
    
    for i in range(1,t):
        e=goal-M1 # 偏差です
        
        M=Kp*e # 今回の今回の操作量です
        print(M1+M)
    
        M_list.append(M1+M)
        t_list.append(i)
        
        M1=M+M1　
    
    plt.hlines([goal],0,t,"red",linestyles="dashed") # 指定した定義域に、指定した高さでラインを引く関数
    plt.plot(t_list,M_list,color="b")                # プロットする関数
    plt.ylim(0,goal*2)                               # グラフの表示範囲
    plt.show()
    
```
CC BY-SA 4.0
2020-09-12T23:05:39.843
70335
2020-09-13T05:29:50.477
2020-09-13T05:28:35.653
3060
41334
question
python python3 matplotlib sympy scipy
このコードはP制御になっていますでしょうか？
単に計算の過程で丸められただけだと思います。

プログラムで計算する際、数値を 4byte や 8byte
などの固定のバイト数で表現するので、どうしても細かい数字は四捨五入のような処理をせざるを得ません。  
(どのようにして小数を表現するか: [倍精度浮動小数点数 -
Wikipedia](https://ja.wikipedia.org/wiki/%E5%80%8D%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0))

その結果、例えば10進数5桁の精度しかなかった場合、

```

    89.999 + 0.0008 = 89.9998
                    = 90.000
    
```

のようなことが起こります。

```

    import sys
    
    goal=90
    M1=0.00 
    
    Kp=0.8
    
    t_list=[]
    M_list=[]
    t=50
    t_list.append(0)
    M_list.append(0.00)
    
    print(sys.float_info)  # 小数計算がどのように行われるかを表示
    
    for i in range(1,t):
        e=goal-M1  # 偏差です
        
        M=Kp*e  # 今回の今回の操作量です
        print("M1   = {}".format(M1))
        print("M    = {}".format(M))
        print("M1+M = {}".format(M1+M))
        print()
    
        M1=M+M1
    
```

```

    sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
    M1   = 0.0
    M    = 72.0
    M1+M = 72.0
    
    M1   = 72.0
    M    = 14.4
    M1+M = 86.4
    
    M1   = 86.4
    M    = 2.8799999999999955
    M1+M = 89.28
    
    (略)
    
    M1   = 89.99999999999996
    M    = 3.4106051316484814e-14
    M1+M = 89.99999999999999
    
    M1   = 89.99999999999999
    M    = 1.1368683772161604e-14
    M1+M = 90.0
    
    M1   = 90.0
    M    = 0.0
    M1+M = 90.0
    
    M1   = 90.0
    M    = 0.0
    M1+M = 90.0
    
    (略)
    
```

`sys.float_info` の `epsilon=2.220446049250313e-16` とある部分が、およそ 10^-16~10^-15
の割合の丸め誤差が出ることを示しています。  
実際にその桁数の時に `M`, `M1+M` の値がおかしくなっていることがわかります。

上では固定バイト数で計算すると書きましたが、必要な分だけ動的にメモリを確保して計算するという方法もあります。  
ただし固定バイトの計算と比べて遅いです。細かい数値を表現しようとすると当然ながらその分だけ遅くなるというジレンマ付きです。細かい値が蓄積されると指数関数的に遅くなったりメモリを食いつぶしたりするので、理解のないまま実際のアプリケーションに組み込むのはおすすめしません。  
python だと `fractions.Fraction`
が標準で使えます。これは数値を分数として扱おうというもので、この程度のシミュレーションなら問題なく使えると思います。

```

    from fractions import Fraction
    
    goal=Fraction(90)
    M1=Fraction(0)
    
    Kp=Fraction(8, 10)
    
    t_list=[]
    M_list=[]
    t=50
    t_list.append(0)
    M_list.append(Fraction(0))
    
    for i in range(1,t):
        e=goal-M1 #偏差です
        
        M=Kp*e #今回の今回の操作量です
        print("M1   = {}".format(M1))
        print("M    = {}".format(M))
        print("M1+M = {}".format(M1+M))
        print()
    
        M1=M+M1
    
```

```

    M1   = 0
    M    = 72
    M1+M = 72
    
    M1   = 72
    M    = 72/5
    M1+M = 432/5
    
    M1   = 432/5
    M    = 72/25
    M1+M = 2232/25
    
    (略)
    
    M1   = 12789769243681803345680236816406232/142108547152020037174224853515625
    M    = 72/710542735760100185871124267578125
    M1+M = 63948846218409016728401184082031232/710542735760100185871124267578125
    
    M1   = 63948846218409016728401184082031232/710542735760100185871124267578125
    M    = 72/3552713678800500929355621337890625
    M1+M = 319744231092045083642005920410156232/3552713678800500929355621337890625
    
```
CC BY-SA 4.0
2020-09-13T00:55:10.357
70337
2020-09-13T05:29:50.477
2020-09-13T05:29:50.477
3060
20885
70335
answer