今さらPython3(6) - mathの続き

前回、この本のAppendix Cにあるmathをいじり始めたのですが、終わらなかったのでもう少し継続してみます。

入門 Python 3

入門 Python 3

高校数学以来の虚数

>>> 5
5
>>> 8j
8j
>>> 3 + 2j
(3+2j)
>>>

2乗すると-1になる値をiと定義するって習ったけど、Python3ではjを使うそうで。実世界でどういうときに虚数を使うのかなと思って調べてみたところ、自分が数学以上に苦手だった物理の世界では使うそうですね。

・・・へぇ。としか言えない。

英語だとimaginary numberというそうです。はぁ、そうですか、豆知識が1個増えましたw

>>> 1j * 1j
(-1+0j)
>>> j **
  File "<stdin>", line 1
    j **
       ^
SyntaxError: invalid syntax
>>> j ** 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1j * 1j
(-1+0j)
>>> (7 + 1j) * 1j
(-1+7j)

これらの結果も示唆に富んでいますね。Pythonの中で、いくら虚数はjだとと言っても、jをそのまま使うと変数名と間違えられるので、1jみたいに書かないとダメ。ということで、1jどうしを掛け合わせると、-1になるのかなと思ったら、(-1+0j)と返ってくる。

妥当と言えば妥当な結果にも見えます。

小数点以下の精密な?計算

>>> 10.0/3.0
3.3333333333333335

ワォ!なんで最後に5が?と、この本の英語版の台詞をパクらせてもらいましたが、小数点以下のある程度精密な計算には、floatじゃなくてdecimalを使いなさいという事なのですね。

>>> from decimal import Decimal
>>> price = Decimal('19.99')
>>> tax = Decimal('0.06')
>>> total = price + (price * tax)
>>> total
Decimal('21.1894')

Decimal型に変換するのに何で文字型(str)で渡しているんだろうと不思議に思い、floatでも渡してみたらこうなったと。

>>> price2 = Decimal(19.99)
>>> tax2 = Decimal(0.06)
>>> total2 = price2 + (price2 * tax2)
>>> total2
Decimal('21.18939999999999829862762368')

結果を見たら、strで渡しておきなさいよと言うのは明らかですね。floatが精密計算に向かないのは、何もPythonに限った話ではないけど、公式文書にも説明されているので、気になる場合は、これを読むべし。

15. 浮動小数点演算、その問題と制限 — Python 3.4.3 ドキュメント

その続きにあるのは、丸めの話ですね。

>>> penny = Decimal('0.01')
>>> total.quantize(penny)
Decimal('21.19')
>>> penny = Decimal('0.001')
>>> total.quantize(penny)
Decimal('21.189')
>>> penny = Decimal('0.1')
>>> total.quantize(penny)
Decimal('21.2')

これって便利じゃん。例えば、0.05ごとに丸めるとかできるの?とやってみた。

>>> penny = Decimal('0.05')
>>> total.quantize(penny)
Decimal('21.19')

ダメなんかい!ちょっと期待してた自分がおバカだった。。。

分数の計算

分数のことを英語でfractionというのですね。初めて知りました。

>>> from fractions import Fraction
>>> Fraction(1,3) * Fraction(2,3)
Fraction(2, 9)

これは、1/3 * 2/3 = 4/9 をやったということ。

>>> Fraction(1.0/3.0)
Fraction(6004799503160661, 18014398509481984)
>>> Fraction(Decimal('1.0')/Decimal('3.0'))
Fraction(3333333333333333333333333333, 10000000000000000000000000000)
>>> Fraction(Decimal('3.0')/Decimal('1.0'))
Fraction(3, 1)
>>> Decimal('3.0')/Decimal('1.0')
Decimal('3')

これもfloatじゃなくてDecimal使おうよという一環なんだけど、素直にFraction(1,3)と出てくれればいいのに。。。

>>> fractions.gcd(24,16)
8

これは最大公約数を出す。最小公倍数を出すものはfractionsの中にはないのね。

9.5. fractions — 有理数 — Python 3.3.6 ドキュメント


このままAppendix Cを突っ走るとキリがないので、一旦本文に戻ります。

(つづく)