SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

Python 3.0開発者ガイド:数値、文字列、データ

数値、文字列、バイナリデータの基本データ型の処理

PEP 238:除算演算子の変更

 Python 2.xでは、除算演算は整数の除算と浮動小数点数/複素数の除算に分かれていました。整数の除算は切り捨て除算で、除算結果は最も近い整数(intまたはlong)になるように切り捨てられます。

>>> 5 / 2
2
>>> -5 / 2
-3

 浮動小数点数と複素数の除算は、いわゆる「真の除算(true division)」であり、算術演算として妥当な近似値が返されます。

>>> 5.0 / 2
2.5
>>> -5 / 2.0
-2.5
>>> complex(5, 0) / 2
(2.5+0j)

 2種類の除算が存在するのは、言語のデザインにおいて非常に深刻な問題と言えます。整数と浮動小数点数や複素数の演算を行うアルゴリズムを作成する場合は、非常に厄介なことになります。例えば関数ライブラリを開発するときに、真の除算を行うようにしたいと思っても、どうすれば安全に実現できるのか、すぐには明確な答えが見つかりません(__future__による回避策については後述します)。

 例えば、整数、浮動小数点数、複素数の平均値を返す関数を作成するとします。単純な方法として次のようなコードが考えられます。

def average(*numbers):
  return sum(numbers) / len(numbers)

 対象となるすべての数値が整数で、平均値が整数でない場合には、この関数は失敗します。

>>> average(1,4)
2

 では、どのようにすれば真の除算ができるのでしょうか。すべての引数を浮動小数点数型に変換するという方法では、複素数があると対応できません。すべての数値に0.0を足すという方法では、元の数値が浮動小数点数-0.0の場合に符号が消えてしまいます(IEEE 754の浮動小数点数標準によると、0.0と-0.0は同一値ではありません)。

>>> x=-0.0 
>>> x
-0.0
>>> x + 0.0
0.0

 型と符号を維持し、かつ、真の除算を行う唯一安全な方法は、引数を1.0倍することです。この方法は、単純なaverage関数を作成しようとするときに容易に考えつく方法とは言えず、無視できないオーバーヘッドもあります。

def average(*numbers):
  return sum([n * 1.0 for n 
     in numbers]) / len(numbers)
  
>>> average(1,4)
2.5

 幸い、Python 3.0では、除算は常に真の除算となり、(結果が整数でも)浮動小数点数または複素数(オペランドに複素数がある場合)を返します。

>>> 5 / 2
2.5
>>> -5 / 2
-2.5
>>> 4 / 2
2.0
>>> complex(5, 0) / 2
(2.5+0j)

 Python 3.0で切り捨て除算を行うには、//演算子を使用します。両方のオペランドが整数の場合、結果は整数になります。オペランドの一方が浮動小数点数で、もう一方が浮動小数点数または整数の場合、結果は浮動小数点数(ただし、整数と等しい浮動小数点数)になります。切り捨て除算は複素数には対応しません。

>>> 5 // 2
2
>>> 5.0 // 2
2.0
>>> complex(5,0) // 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't take floor of a complex number.

 あまり知られていませんが、明示的切り捨て除算は、Python 2.2から使用できました。また、真の除算の動作も、Python 2.2で次のステートメントを使用することによって利用できます。

from __future__ import division

 これは、Python 3.0へ移行するコードを段階的に準備する場合に便利です。数値処理コードがある場合、またはPython 2.x方式の除算を行うコードを呼び出す場合、厄介なバグが発生する可能性があります。除算演算子を実際に使用しているコードを変更するだけではなく、呼び出し側もすべて確認しなければならなくなるからです。Python 3.0移行時の除算演算子対策に関するさらに具体的な情報については、今後の記事で取り上げる予定です。

 インタープリタに-Qコマンドライン引数を渡して、除算の動作を制御することもできます。この引数に指定できる値は、old(デフォルト)、warnwarnallnew(真の除算)です。ただし、これを行う意味と理由を十分に理解している場合を除き、この方法はお勧めしません。除算のような重要な動作の制御をコマンドライン引数に依存するのは、極めて危険です。

次のページ
浮動小数点数の改善点

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Gigi Sayfan(Gigi Sayfan)

 主に大規模分散システムを対象とした、C/C++/C#/Python/Javaによるクロスプラットフォームのオブジェクト指向プログラミングに精通。現在は、Numenta社で脳の働きを模した人工知能システムの開発に取り組んでいる。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4052 2009/06/29 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー