#pythonのdocumentationとにらめっこしてて初めて気づいたんですが
#pythonって浮動小数数点数の16進表記がサポートされてるんですね
#lispでそういうのがないのは, rationalがリテラルとしてあるからなんでしょうか?
#16進表記だと誤差なく浮動小数点数が表現できます
#16進小数点数表記はかなり前からGaucheでサポートしたいと思ってるんですが、良い構文を思いつかなくて止まってます。
#誤差に関していえば、lisp界ではread/write invarianceの関係で浮動小数点数の読み書きで誤差が生じないのが普通という空気はあったと思います。
#ただ、誤差の生じない表現への変換って重いんですよね。CGだと大量の浮動小数点数データをやりとりしたりするんで、16進リテラルは速度的に有利だろうなと思ってました。
#pythonの場合はリテラルではないですねー
#float.from_hex("0x1.ab3p+2")みたいにして
#浮動小数点数に直してますね
#CGの話だと, 人が読み書きできるフォーマットへの書き出しを意識しているんでしょうか?
#はい。構造化されたデータになるわけですが、全部バイナリにしちゃうと扱いが面倒だし、構造部分だけテキストでバルクのバイナリデータを別ファイル、というのもややこしいんで、全部テキストでいざとなれば構造部分を手で編集できるけど読み書きは速い、っていうのがあったらいいかなと。
#なるほど
#最近個人的に浮動小数数点数の誤差にとても敏感なお年頃なので, gaucheでinterval arithmeticをサポートしてくれれば良いアピールになるのではとか思っちゃいます
#Pythonの「Since Python’s floats are stored internally as binary numbers, converting a float to or from a decimal string usually involves a small rounding error. In contrast, hexadecimal strings allow exact representation and specification of floating-point numbers.」という説明は正確じゃないな。きちんとルールを決めれば、浮動小数点数の10進表記と内部表現をちゃんとマッピングすることは可能。
#a
#あ、そうなんですか. 内部表現-->10進表記も可能なんですか?
#内部->10進は常に可能ですよ。1/2^nは10進で循環少数にはならないので。10進->内部は2進で循環少数になっちゃう場合がありますが、「最も近い表現可能な2進数に丸める」とすれば、
#「少なくとも計算機で扱うことが可能な浮動小数点数は、それを書き出して、再び読みもどしたときに、常に元の内部表現が得られることを保証できる」とは言えます。
#ああ, そうか. 内部->10進は必ず有限な桁数で表示できるんですね
#そうそう, schemeではinexact?みたいな述語があって正確な数値かどうかに結構気を使っている印象があるんですが
#読み込み時の丸めを考慮して、「必要最小限の桁数で出力する」というアルゴリズムがあります。
#floatの>/<に関しては特に何もないなぁというのが気になります
#<とかで#tと#fのほかに誤差があるので不定みたいな返り値があってもいいんじゃないかと思ってしまいます
#それを考え出すと「不正確なboolean」とか出てきちゃいそうですからねえ
#多値にしておいて, 2つ目以降に正確かどうかを#t/#fで返すとか良いなぁと
#interval arithmeticはおもしろそうだけれど、自分で使わないから勘どころがわからないんですよねえ。「こういうプリミティブだけコアでサポートしたら後はライブラリで書ける」ってな感じで教えてもらえたら、それを実装するのにはやぶさかではないです。
#interval arithmeticの使いどころは, アプリとしては例えば衝突判定とかです
#少し浮動小数数点数の値が変わっただけで真偽値がひっくり返ってしまうので
#CGALとかでは至る所につかってるらしいのですが, 僕もあんまり詳しくないので... http://www.cgal.org/ #なるほど。私はゲームの感覚なので、衝突判定は速度重視、誤差はアプリ側で吸収、ってつい思っちゃうな。
#レンダリングの時はjitterかけて散らしちゃえ、とか。
#僕はロボットの感覚なので, 衝突判定の不安定さがモロに効いてくるところがあります
#厳密にやりたいという用途があることはわかります。
#僕はまだinterval arithmeticに興味があるレベルなのでなんとも言えないですが, プリミティブとしては, boostのものが参考になるのかもしれません.
##静的型だとインターバル情報を余分なアロケーション無しでやりとりできるけど、動的型でナイーブにやろうとしたらインターバル付き数値をひとつ作る度にひとつアロケーションが入って嬉しくないな。
#デフォルトで実は誤差情報が影の値として伝搬してて、欲しければ取り出せる、なんて感じになってるとおもしろそうだ。
#そうそう, 実はinterval arithmeticはオーバーヘッドはそんなに大きくないという話を聞いたことがあります. もちろんアロケーションが無くてすむ場合ですが. たしか2倍遅くなるくらいだったかな
#演算の数としては確かにだいたい2倍ってわけですからね。レジスタやキャッシュを圧迫するとかありそうだけど、そんなに問題にならないのかな。
#む。今Gaucheでは計算途中のflonumの生成はnursery使うので非常に速いんだけど、デフォルトでflonumに誤差情報もつけちゃうことにしたら、実はアロケーションはあんまり問題にならなかったりして。もちろんキャッシュの圧迫とかはあるけど。
#毎回3つ(min, max, 代表値)を計算するのだからSSEで一気にとかいう最適化でコストは減らせたりする気もします
#ああ、3つ持たないとならないのか。上と下の誤差が違うことがあるから。
#上でちょっと考えてたのは、今 struct ScmFlonumRec { double val; } として持ってるflonumを、 struct ScmFlonumRec { double val[3]; } としてしまえばどうか、というもの。普通の計算ではひとつしか使わないけれど、何らかのフラグか、あるいは別のセットの関数群を使った時は、余分なスロットをinterval arithmeticに使う。アロケーションの量は増えるが回数は変わらないからいけないかな、と思った。んだけど、flonumのnurseryをflushする時のコピー量も増えるからあまり美味しくはないかもしれない。
#ほわぁ〜、ひとつ年内までという約束をぎりぎりで守れそうだ。が。予想外に時間をとって他の諸々が押しまくりである。年末年始なにそれおいしいの。せめて大晦日に掃除くらいはしたいものだが。