http://oss.timedia.co.jp/index.fcgi/kahua-web/show/ossz/oneline/2006-04-17
出題され
http://oss.timedia.co.jp/index.fcgi/kahua-web/show/ossz/oneline/2006-04-18
で答えが出ているが、無限大を使っているのが不満であった。それに、計算誤差で負ける。
計算誤差で負けると言えば、私が先日書いた id:Nabetani:20060418:p1 も計算誤差で負ける。
というわけで。
f(f(x))==-x となり、無限大になったり計算誤差で負けたりしないものを haskell, ruby, C で書いてみた。
まずは haskell 版:
f x | x==0.0 = 0.0 | ((e+2048) `rem` 2)==0 = encodeFloat n (e+1) | otherwise = - encodeFloat n (e-1) where (n,e) = decodeFloat x
次は C 版
double f( double d ) { if ( d==0 ){ return 0; } else { int e; double n = frexp( d, &e ); return ( e+2048 )%2==0 ? ldexp( n, e-1 ) : ldexp( -n, e+1 ) ; } }
最後に ruby 版
def f( d ) if d==0 0; else n, e = Math.frexp( d ) s = ( e+2048 )%2==0 Math.ldexp( s ? n : -n, e + ( s ? -1 : 1 ) ) end end
見ての通り、全部一緒。
浮動小数点の実装に触れているので若干邪悪な感じではあるが、そういうもんだとも思う。
書いていて。haskell の where が便利だと思った。
#写真と本文は関係ありません