2016/05/21(土)カシオの関数電卓の奇妙な挙動

カシオの関数電卓をいじっていて、とても奇妙な挙動に気づいたので記録を残しておきます。使用したのはfx-5800Pという機種で、内部演算精度は10進数15桁です。結論から書くと、次のような現象を発見しました。
123456789123456 - 123456789121111 = 2345
123456789123456 - 123456789123111 = 345
123456789123456 - 123456789123411 = 0 (45でない!)
非常に近い2つの数同士の引き算を行なうと、「桁落ち」と呼ばれる有効数字の減少が発生します。これは有限精度の計算を行っている以上仕方のないことですが、どうやらこの関数電卓では、
「減算で桁落ちが発生した結果有効数字が2桁以下になったとき、その数を強制的に0に書き換える」
という仕様になっているようです。桁落ちが起きるような厳しい計算こそ高精度な電卓の助けが欲しいところなのに、そこでわざわざかろうじて残った情報を捨て去ってしまうというのは極めて不可解な仕様だと感じます。

この仕様で困ってしまう場面はいくらでもありそうですが、一つ例を作ってみました。2次方程式
0.9999996 x2 - 2x + 1.0000004 = 0
の解をいわゆる2次方程式の解の公式で計算してみます。判別式の値は、
4 - 4 × 0.9999996 × 1.0000004
= 4 - 3.99999999999936
= 0.00000000000064
= 6.4 × 10-13
ですが、この値が
4 - 3.99999999999936 = 0
となってしまいます。3.99999999999936を正しく格納できる仮数部を持っているにも関わらず、です。実にもったいない仕様だとは思いませんか。素直な10進数15桁の演算ならば、
sqrt(6.4 × 10-13) = 8 × 10-7
x1 = (2 - 8×10-7)/2/0.9999996 = 1
x2 = (2 + 8×10-7)/2/0.9999996 ≈ 1.000000800000032
のようにほぼ正確に計算できたはずなのに、
x1 ≈ 1.00000040000016
x2 ≈ 1.00000040000016
のような重解になってしまいます。また、手作業で解の公式を使って計算した場合のみならず、関数電卓に組み込まれた2次方程式ソルバーを使っても全く同じ計算結果が得られました。すなわち、ユーザに直接見える部分のみならず、内部の演算ルーチンそのものがこの仕様に蝕まれていることは確実と思われます。

この仕様はカシオfx-5800Pに特有のものなのか、他の機種にも見られるものなのか、ヨドバシカメラの関数電卓売り場の展示機を触って調べてみました。すると、
機種名仮数部の桁数桁落ち時に捨てられる桁数
カシオ fx-5800P/JP900/FD10Pro/375ES/72F152
キヤノン F-789SG182
キヤノン F-715SA163
シャープ EL-509M141
のようになりました。試した限りの全ての関数電卓で、桁数の違いこそあれこのような「過桁落ち」処理がなされているようです。全く理解できないのですが、どなたか事情をご存知なら教えて欲しいものです。

2016/05/01(日)emscriptenで遊んでみた

emscriptenという、c/c++のコードをLLVMのバイトコードを経由してjavascriptに変換するコンバータがよく話題になっています。以前、kvライブラリをemscriptenで変換して動かしたというメールを頂いたことがあって、ずっと気になっていました。そこで、ちょっとインストールして遊んでみました。

インストールしたばかりのubuntu 16.04で試しました。しかし、
sudo apt install emscripten
で入れてもうまく動かない模様です。clang/llvmのバージョンの問題っぽいがよく分かりません。

そこで、本家の Download and install — Emscripten 1.36.1 documentation に従ってインストールしてみました。そこではポータブル版というroot権限なしで入れる方法が紹介されていました。その方が周辺ツールのバージョンに左右されなくてインストールが楽なのかな。
sudo apt install cmake
Portable Emscripten SDK for Linux and OS X (emsdk-portable.tar.gz) をダウンロードして展開し、その中にcdして
./emsdk update
./emsdk install latest
./emsdk activate latest
します。最後の作業で/home/kashi/.emscriptenが作られました。これでインストールは終了。使う前に
source emsdk_env.sh
でPATHの設定が必要です。

適当なc++のプログラムを作って、
emcc test.cc
node a.out.js
で動くのを確認しました。

次に、kvのプログラムを動かしてみました。問題はboostで、emscriptenでは外部ライブラリを使ったプログラムはそのままでは動きません。外部ライブラリもソースから変換する必要があります。kvの場合は幸いなことにboostはheader onlyの範囲でしか使っていませんので、大丈夫なはずです。自分は、
ln -s /usr/include/boost ホームのどこか
とリンクを張ってしまって、-Iにそれを指定してごまかしました。これが正しいかどうかは分かりません。また、javascriptの中ではfesetroundによる丸めの向きの変更は効かないので、そのままでは精度保証出来ません。kvは-DKV_NOHWROUNDを付けると丸めの向きの変更を行わずエミュレーションで方向付き丸めを行なう機能を持っており、それをつけるとちゃんと精度保証付きで計算してくれるようです。
emcc -I(kvの場所) -I(boostの場所) -DKV_NOHWROUND hoge.cc
みたいな感じです。kvのサンプルはmpfrを使ったもの以外は大体動きそうです。実行速度はちゃんと測ってませんがネイティブのC++の30倍程度でしょうか。htmlに変換してfirefoxに食わせた方がnode.jsより速いようにも見えました。

単なる遊びであってあまり意味はないですが、楽しいです。

2016/01/28(木)googleのAlphaGoが人類を超えた!?

昨日の深夜に発表され、瞬く間に大騒ぎになったgoogleの囲碁AIがプロに勝った件、メモ代わりにまとめておきます。

最初に知ったのは、現在最強の囲碁プログラムの一つ、Crazy Stoneの作者のつぶやきでした。そこにyoutubeへのリンクが。まもなく、NHKの記事が出て、それらによると、googleがネイチャーに論文を発表し、AlphaGoと名付けられた囲碁AIが史上初めて人間のプロ棋士にハンデ無しで勝ったということでした。
  • 中身はモンテカルロ木探索にディープラーニングを組み合わせたもの
  • 中国のプロに5戦全勝
  • 3月に現在人類最強の一人と思われるイ・セドルと対局
ネイチャーの論文は
にありますが、基本的に有料です。

googleのブログの記事はこちら
開発の中心となったのは、最近Googleに買収されたイギリスのAIを研究するDeepMind社のDemis Hassabis氏。DeepMind社の記事はこちら。
この記事中に、無料で読める論文のプレプリントへのリンクがあります。

まだ論文は読んでいませんが、既存の最強の囲碁ソフトに500戦499勝とか、既存の最強の囲碁ソフトに4子おかせて勝率8割とか、恐ろしい噂が聞こえてきます。プロ棋士に勝った棋譜を見た感想もとても強いというものが多く、3月のセドルとの対局が楽しみです。

2015/03/23(月)MSYS2を試してみる

日頃、研究のための作業のほとんどをubuntu上で行っています。研究者の多くはunix系の環境で仕事をすることを好んでおり、
  • macを使う。
  • windowsでvmware等の仮想環境を作り、その中でLinux等を使う。
  • windowsでcygwinを使う。
  • Linux等をマルチブートで使う。
などいろいろあると思います。本当に素のwindowsで仕事をする人は少ない気がします。拙kvライブラリも一応Visual Studioでも動くもののunix系で開発している関係上やはりunix系OSが使いやすい気がします。研究室の学生を見ると、windowsでcygwinを使っている人が大半のようです。自分はLinuxを入れることを勧めているのですが、やはり不慣れなOSで生活するのはつらいようで。

さて、windows環境のままunix系コマンドを使えるようにするソフトウェアとしてはcygwinが有名で長く使われてきていますが、最近MSYS2という同様のソフトウェアのいい評判をよく耳にします。そこで、試しにちょっと使ってみました。

元々、cygwinの亜種でmingw+msysというwindows nativeのexeを生成するソフトウェアがあるのですが、それの後継という位置づけで、
  • 比較的アップデートが早く、最新のソフトウェアが使える。
  • Arch Linuxで使われているpacmanというパッケージマネージャが使える。
という特徴があります。
上のページを見ながら、試しにインストールしてみました。インストール先はwindows7 64bit。
  • 64bit版のexe (msys2-x86_64-20150202.exe) をダウンロード。
  • 普通にインストーラを起動してインストール。デフォルトのc:\msys64に入れた。
  • スタートメニューからmsys2 shellを起動、終了、を2回繰り返す。
  • msys2 shell上で、最新にアップデートする。
    pacman -Sy(repositoryのデータを最新に)
    pacman --needed -S bash pacman pacman-mirrors msys2-runtime (再起動の必要のあるものを先にupdate)
    (msys2 shellを再起動)
    pacman -Su (残りをupdate)
    
pacmanパッケージマネージャの使い方は、以下の通り:
  • pacman -Ss 名前 で検索。
  • pacman -S 名前 でインストール。
  • pacman -R 名前 で削除。
さて、ややこしいことに、MSYS2はmsys2, mingw32, mingw64の3種類のbinaryを含んでおり、それぞれインストール場所も分けられています。msys2は、(cygwinがそんな感じであるように)msys-2.0.dllというmsys2独自のDLLがリンクされており、MSYS2環境下でしか動かないbinaryです。mingw32, mingw64はそれぞれwin32, win64のbinaryで、単独で動作します。gcc等のコンパイラも3種あって、msys2コンパイラで生成したexeはmsys2のDLLに依存しますが、mingw32/64のコンパイラで生成されたexeは単独で動作します。また、スタートメニューに登録された起動バッチファイルはmsys2_shell.bat, mingw32_shell.bat, mingw64_shell.batの3種類あって、msys2_shell.batから起動するとmsys2なbinaryにしかパスを通しません。mingw32/64.batで起動すると、mingwとmsys2の両方のbinaryにパスが通され、mingwの方が先に登録されているので優先されます。なるべく全てのbinaryをwindows nativeにしたかったが、どうしても無理なものだけmsys2依存で作成している、ということだと思います。

自分は、mingw64_shell.batを常用することにしました。

いくつかパッケージを入れて開発環境を整えてみました。前述したようにgccは3種類ありますが、公式Wikiの"Contributing to MSYS2"にあるように
pacman -S base-devel
pacman -S msys2-devel
pacman -S mingw-w64-i686-toolchain
pacman -S mingw-w64-x86_64-toolchain
で主だった開発に必要なものは大体入ります。更に、
pacman -S vim
pacman -S mingw-w64-x86_64-boost
pacman -S openssh
あたりを入れてみました。

この環境でkvライブラリはちゃんとコンパイル出来ました。mpfrを使ったものも、-lmpfr -lgmpを付けるだけでOK。

アンインストールも試してみましたが、コントロールパネルからで普通にきれいさっぱり消せるようです。

gccは4.9.2、boostは1.57.0であり、sshの最近のバグも修正されるなど、最新の環境が楽に使えるのはとてもいいですね。しばらく注目していようと思います。

2014/11/13(木)Intel Edison

IntelのEdisonとかいう謎アイテムを買ってみました。
切手くらいの大きさにx86 CPUと4Gストレージ、1Gメモリ、無線LANとBluetoothが載って単体でLinuxが動く。こういう変なものはとりあえず買うしかないでしょう。単体だと特殊コネクタしかなくて手も足も出ないので、USBとかのI/Fを引き出してくれるBreakoutボード付きのものを買いました。税込8640円。

IMG_5272.JPG


組み立ては差し込んでネジ止めするだけ。

IMG_5282.JPG
IMG_5283.JPG


以下は設定メモ。母艦としてubuntuの入ったPCを使った。
  • J3とPCをmicroUSBケーブルで繋ぐ。これはシリアル通信のためのもの。syslogを見るとttyUSB0として繋がってるっぽいので、
    sudo screen /dev/ttyUSB0 115200 -L
    
として繋ぐ。
  • さらに、J16とPCをmicroUSBケーブルで繋いで電源供給する。ログイン画面になるので、ID:rootでパス無しで入れることを確認。
  • 初期バージョンはバグだらけらしいので、https://communities.intel.com/docs/DOC-23242から"Edison Yocto complete image"をダウンロードし、https://communities.intel.com/docs/DOC-23200を見ながらアップデート。ドキュメントの最後に載ってる flashall.sh を使う方法でうまくいった。
  • シリアルで繋いだterminalから
    configure_edison --setup
    
    を実行。ホスト名、パスワード、Wi-Fiを設定し、これ以降は無線LAN経由でsshで操作できるようになる。
参考にしたサイトは、
あたり。

さて、sshで中を見ると、gcc 4.8.2が入っていて、セルフ開発出来そうです。とりあえずkvライブラリで精度保証ができるか試してみました。boostとkvライブラリを転送し、実行してみると、あっさり動きました。

とりあえず西先生の 5 solution の全解探索を実行してみると、
  • 5.7sec (core i7 4600U)
  • 137sec (Intel Edison)
となりました。さすがに速度差は歴然ですね。
Edisonは32bitにしか対応していないのですが、SSE2を持っているので-msse2 -mfpmath=sseをコンパイルオプションに指定すれば浮動小数点計算をSSEにやらせることができ、高速かつIEEE754準拠になります。
OK キャンセル 確認 その他