鍋あり谷あり

テーマを決めずに適当に書いています。

f(f(x))==-x の答え

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 が便利だと思った。

#写真と本文は関係ありません