NOEMBLEM/エンブレムが設定されていません。

メールの詳細(トピック表示)

はじめまして/gawkでfibbizzやっていた所、計算が合わないケースがありました

投稿者:houmeiさん  2011/10/16 05:04  MLNo.256   [メール表示]

はじめまして、houmei/竹下と申します。よろしくお願いします。

fibbuzzという、フィボナッチ数列に対してfizzbuzzをするという遊びをawkでやっていたところ、どうも答えが異なってしまう現象がおき悩んでいました。ある程度絞り込めましたのでご報告します。

動作環境:MacOSX(10.6.8) /標準のawkとhomebrewでインストールしたgawk
awk version 20070501
GNU Awk 4.0.0
実行例:
gawk 'BEGIN{print 5527939700884757+8944394323791464}'
→14472334024676220 ※最後の桁が"1"でない

なお、rubyでは正しく計算できています。
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin10.0]

ruby -e 'print 5527939700884757+8944394323791464'
→14472334024676221

どういった境界で発生するのかまでは追求できていません。取り敢えずご報告まで。


 読み込み中...

  • MLNo.257   houmeiさん  (0) 2011/10/16 06:06  [メール表示する]
    竹下です。gawk3.1.6でも再現しました。(ideone.com) http://ideone.com/37P7Y

    さらに絞り込んでみました。

    16進表示に直しました:(clisp)
    Break 1 [4]> (format nil "~X" 5527939700884757)
    "13A3A1C2360515"
    Break 1 [4]> (format nil "~X" 8944394323791464)
    "1FC6E116668E68"

    再現確認:
    $ gawk 'BEGIN{print 0x13A3A1C2360515+0x1FC6E116668E68}'
    14472334024676220
    絞り込み:
    $ gawk 'BEGIN{print 0x13000000000005+0x1F000000000008}'
    14073748835532812

    $ gawk 'BEGIN{print 0x01000000000000+0x1F000000000001}'
    9007199254740992
    $ gawk 'BEGIN{print 0x01000000000000+0x1E000000000001}'
    8725724278030337

    16進で13桁目の繰り上がりで末尾の'1'が加算されていないように見えます。

    同じ繰り上がりでも0x01.. + 0x0F.. ではうまくいきます。
    $ gawk 'BEGIN{print 0x01000000000000+0x0F000000000001}'
    4503599627370497

  • MLNo.258   ほげむたさん  (0) 2011/10/16 11:45  [メール表示する]
    木村です。

    2011/10/16 houmei :
    > はじめまして、houmei/竹下と申します。よろしくお願いします。
    >
    > fibbuzzという、フィボナッチ数列に対してfizzbuzzをするという遊びをawkでやっていたところ、どうも答えが異なってしまう現象がおき悩んでいました。ある程度絞り込めましたのでご報告します。
    >
    > 動作環境:MacOSX(10.6.8) /標準のawkとhomebrewでインストールしたgawk
    > awk version 20070501
    > GNU Awk 4.0.0
    > 実行例:
    > gawk ''BEGIN{print 5527939700884757+8944394323791464}''
    > →14472334024676220 ※最後の桁が"1"でない
    >
    > なお、rubyでは正しく計算できています。
    > ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin10.0]
    >
    > ruby -e ''print 5527939700884757+8944394323791464''
    > →14472334024676221
    >
    > どういった境界で発生するのかまでは追求できていません。取り敢えずご報告まで。

    homebrew とあるのでgccが使えると思いますが、こんなのをコンパイル&実行してみてください。

    #include

    double getx() {return 5527939700884757.0;}
    double gety() {return 8944394323791464.0;}

    int
    main()
    {
    int x, y;
    printf("%f\n", getx()+gety());
    printf("%f\n", 14472334024676220.0);
    printf("%f\n", 14472334024676221.0);
    printf("%f\n", 14472334024676222.0);
    printf("%f\n", 14472334024676223.0);
    return 0;
    }

    こんな出力になると思います

    14472334024676220.000000
    14472334024676220.000000
    14472334024676220.000000
    14472334024676222.000000
    14472334024676224.000000

    2**53-1 = 9007199254740991 なので、double で表現できないところに行っちゃってますね。
    では。


    --
    木村浩一/KIMURA Koichi
    I thought what I''d do was, I''d pretend I was one of those deaf-mutes
    or shoud I?
    mail kbk at kt.rim.or.jp
    web www.kt.rim.or.jp/~kbk/zakkicho/index.html

  • MLNo.259   houmeiさん  (0) 2011/10/16 13:15  [メール表示する]
    竹下です。
    その後調べていたら以下のページを見つけました。
    http://gauc.no-ip.org/wiki.cgi?page=BBS-BBS%2F47


    > 木村さんが言うには、gawk は dobule で数値を扱っていて、double の mantis> sa は 52bit (+けちビット) あるので、通常の gawk でも 113383 は計算できます。

     gawkがdouble表現とは知りませんでした。
     木村様には二度教えてもらったことになります(^^;

     ありがとうございました。


メールへの返信はMLのメンバーしかできません。
ゼッタイ住みたい4LDK超!/SUUMO