発展課題:制御構造

素数の判定の改良

処理性能の計測

プログラムの改良1

割り切れるかどうか判定する数値の範囲を最適化

import math

def is_prime(n):
    if n < 2:    # 2未満の数は素数ではない
        return False
    # 2からn-1までの数で割り切れるか確認
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

#-----
number = 101

if is_prime(number):
    print(number, 'は素数です')
else:
    print(number, 'は素数ではありません')

プログラムの改良2

2の倍数のテストを除く

import math

def is_prime(n):
    if n < 2:    # 2未満の数は素数ではない
        return False
    # 2からn-1までの数で割り切れるか確認
    for i in range(2, n):
        if n % i == 0:
            return False
    return True

#-----
number = 101

if is_prime(number):
    print(number, 'は素数です')
else:
    print(number, 'は素数ではありません')
101 は素数です

ニュートン法

複利計算

複利計算

毎年n万円(例えば10万円)ずつ株式投資を行う。

1年間の平均的な利回りはrate%(例えば4%)

year年(例えば40年)後の積み立て元金の合計額を求めよ。

year年(例えば40年)後の元利合計額を求めよ。

# 複利計算値を配列に

sin値の1周期分表示

角度をラジアンで指定

まずはラジアンで

while版

import math

end = 7
step = 0.5

angle = 0
while angle <= end:
    value = math.sin(angle)
    print('角度:', angle, 'sin値:', value)
    angle += step
角度: 0 sin値: 0.0
角度: 0.5 sin値: 0.479425538604203
角度: 1.0 sin値: 0.8414709848078965
角度: 1.5 sin値: 0.9974949866040544
角度: 2.0 sin値: 0.9092974268256817
角度: 2.5 sin値: 0.5984721441039564
角度: 3.0 sin値: 0.1411200080598672
角度: 3.5 sin値: -0.35078322768961984
角度: 4.0 sin値: -0.7568024953079282
角度: 4.5 sin値: -0.977530117665097
角度: 5.0 sin値: -0.9589242746631385
角度: 5.5 sin値: -0.7055403255703919
角度: 6.0 sin値: -0.27941549819892586
角度: 6.5 sin値: 0.21511998808781552
角度: 7.0 sin値: 0.6569865987187891

for版

一般的なrange()は整数列しか生成できないので、整数を指定されたstepの実数に変換する必要がある。

import math

end = 7
step = 0.5

for i in range(int(end / step) + 1):
    angle = i * step
    value = math.sin(angle)
    print('角度:', angle, 'sin値:', value)

for版(numpy arange())

range()と同様な機能を持つが、実数のステップを指定し、実数列を生成できるarange()を使うことができる。

arange()はnumpyに含まれている。

import math
import numpy as np

end = 7
step = 0.5

for angle in np.arange(0, end+step, step):
    value = math.sin(angle)
    print('角度:', angle, 'sin値:', value)

ラジアンではなく度数の指定

次はラジアンの指定ではなく度数の指定で

import math

end = 360
step = 20

for angle in range(0, end+1, step):
    radians = math.radians(angle)
    value = math.sin(radians)
    print('角度:', angle, 'sin値:', value)
角度: 0 sin値: 0.0
角度: 20 sin値: 0.3420201433256687
角度: 40 sin値: 0.6427876096865393
角度: 60 sin値: 0.8660254037844386
角度: 80 sin値: 0.984807753012208
角度: 100 sin値: 0.984807753012208
角度: 120 sin値: 0.8660254037844387
角度: 140 sin値: 0.6427876096865395
角度: 160 sin値: 0.3420201433256689
角度: 180 sin値: 1.2246467991473532e-16
角度: 200 sin値: -0.34202014332566866
角度: 220 sin値: -0.6427876096865393
角度: 240 sin値: -0.8660254037844385
角度: 260 sin値: -0.984807753012208
角度: 280 sin値: -0.9848077530122081
角度: 300 sin値: -0.8660254037844386
角度: 320 sin値: -0.6427876096865396
角度: 340 sin値: -0.3420201433256686
角度: 360 sin値: -2.4492935982947064e-16

出力されたsin値の桁数が多すぎで、正確であるかもしれませんが見にくいですね。

さらには、180度、360度の結果を見ると、計算誤差のせいで、10-16の非常に小さな値が出力されています。

小数点以下5桁程度の出力に有効数字を設定して出力するように変更しましょう。

import math

end = 360
step = 20

for angle in range(0, end+1, step):
    radians = math.radians(angle)
    value = math.sin(radians)
    print(f'角度: {angle:3d} 度, sin値:{value:8.5f}')
角度:   0 度, sin値: 0.00000
角度:  20 度, sin値: 0.34202
角度:  40 度, sin値: 0.64279
角度:  60 度, sin値: 0.86603
角度:  80 度, sin値: 0.98481
角度: 100 度, sin値: 0.98481
角度: 120 度, sin値: 0.86603
角度: 140 度, sin値: 0.64279
角度: 160 度, sin値: 0.34202
角度: 180 度, sin値: 0.00000
角度: 200 度, sin値:-0.34202
角度: 220 度, sin値:-0.64279
角度: 240 度, sin値:-0.86603
角度: 260 度, sin値:-0.98481
角度: 280 度, sin値:-0.98481
角度: 300 度, sin値:-0.86603
角度: 320 度, sin値:-0.64279
角度: 340 度, sin値:-0.34202
角度: 360 度, sin値:-0.00000

値を文字グラフで表示

import math

end = 360
step = 20

for angle in range(0, end+1, step):
    radians = math.radians(angle)
    value = math.sin(radians)
    # sin値を-1から1の範囲でスケーリングして、表示位置を決定
    scaled_value = int((value + 1) * 20)  # 0から40の範囲にスケーリング
    graph_line = ' ' * scaled_value + '*'
    print(f"角度: {angle:3d} 度, sin値: {value:8.5f} | {graph_line}")
角度:   0 度, sin値:  0.0000 |                     *
角度:  20 度, sin値:  0.3420 |                           *
角度:  40 度, sin値:  0.6428 |                                 *
角度:  60 度, sin値:  0.8660 |                                      *
角度:  80 度, sin値:  0.9848 |                                        *
角度: 100 度, sin値:  0.9848 |                                        *
角度: 120 度, sin値:  0.8660 |                                      *
角度: 140 度, sin値:  0.6428 |                                 *
角度: 160 度, sin値:  0.3420 |                           *
角度: 180 度, sin値:  0.0000 |                     *
角度: 200 度, sin値: -0.3420 |              *
角度: 220 度, sin値: -0.6428 |        *
角度: 240 度, sin値: -0.8660 |   *
角度: 260 度, sin値: -0.9848 | *
角度: 280 度, sin値: -0.9848 | *
角度: 300 度, sin値: -0.8660 |   *
角度: 320 度, sin値: -0.6428 |        *
角度: 340 度, sin値: -0.3420 |              *
角度: 360 度, sin値: -0.0000 |                    *

# sin値の1周期分の配列記録

最大公約数

def gcd_loop(a, b):
    while b != 0:
        a, b = b, a % b
    return a

#-----
n = 48
m = 18
print(n, m ,"の最大公約数は", gcd_loop(n, m))
n = 101
m = 71
print(n, m ,"の最大公約数は", gcd_loop(n, m))
48 18 の最大公約数は 6
101 71 の最大公約数は 1