パスワードを忘れた? アカウント作成
34704 journal

TarZの日記: 10進演算で出たネタをまとめてみた 6

日記 by TarZ

 東京海上日動の新システムはCOBOLを採用のストーリーで出たネタが面白かったのでまとめてみた。

# ただ、私は言語オタクではないので、色々な言語について詳しく知っているわけではない。(ミスがあったらご指摘ください)

お題 : 手近な言語で0.1を1万回足してみなよ。(#1417986)

(#1418003) VB
@をつけるとDecimal型で解釈される。誤差なし。

(#1418010) Ruby
BigDecimalだから誤差なし。

(#1418056) VB Script
誤差あり。

(#1418017) AWK
誤差あり。続くコメントも参照。

(#1418039) C82-BASIC (CASIO FP-1100)
8ビット時代の有名な10進演算BASIC。もちろん誤差なしで1000となる。

(#1418047) Haskell
私は使ったことがないのでよく判らないのだが、このケースでは10進演算していないので誤差あり。

(#1418087) Python
Decimalなので誤差なし。

(#1418118) Java
java.math.BigDecimalでの演算なので誤差なし。コード例も書いてほしかった…。

おまけ
(#1418148) ぴゅう太 日本語G-BASIC
確か、ぴゅう太のBASICは整数のみだったはず。よって、Line 30でエラー。

-

[18:47 追記] - - - - - - - -

 言語マニアな皆様、コメントありがとうございます。/.Jの片隅に、こんな有用なコメントが集まってよいのでしょうか。

 ただ今、この課題(#1418561)を読み解き中。(うひょー、SIMD演算命令って読み慣れない。命令セットとにらめっこしつつ読み読み)
 この例では、IA32 SIMD命令の8ビット比較(PCMPGTB)を使って桁上がりの検出~処理をしているのでゾーン10進ですが、ビット演算を駆使してパック10進にできないかなあ。

 余力のある方は、こちらの課題もどうぞ。(#1256654)

Z80 & 1024バイトのメモリを駆使して、自然対数の底をBCD100桁求める

 戦略はあるのですが、とても64バイトにできそうにないです…。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by okky (2487) on 2008年09月10日 15時47分 (#1418747) ホームページ 日記
    結構厄介で、特に print の際に丸めが入るケースと、計算時に生じる誤差(2進数計算なのか10進数計算なのか)と絡むと、正しく理解している人はほとんどいません。

    まとめてもらって助かります。

    # 論文とかでかなりあるんですよ。2進数で計算して誤差が出ているのに、
    # printf()が四捨五入する際の誤差と合わせると、「誤差が多い計算法」
    # の方が「たまたま精度が高くなる」のを、安定した低誤差法と間違えているケースが。
    # 査読などをやっていると、こういう間違いを指摘し、正すのが大変で…
    --
    fjの教祖様
  • by C0FFEE (36377) on 2008年09月10日 15時05分 (#1418717) 日記
    java.math.BigDecimal

    <%@ page import="java.math.BigDecimal;"%>
    <%
      BigDecimal sum   = new BigDecimal("0"  );
      BigDecimal value = new BigDecimal("0.1");
      for (int i = 0; i < 10000; i++) {
        sum=sum.add(value);
      }
      out.println(sum.toString());
    %>
    最後の出力は

    <%=sum%>
    で良いとか、contentTypeが無いとかツッコミは無しで。
  • by C0FFEE (36377) on 2008年09月10日 16時09分 (#1418762) 日記
    firefox3,safari3,opera9,chrome,ie6
    =1000.0000000001588

    <script>
    var sum = 0;
      for (var i=0 ; i < 10000 ; i++){
       sum = sum + 0.1;
      }
    alert(sum);
    </script>
    WScript(JScript)
    =1000.00000000016

    var sum = 0;
      for (var i=0 ; i < 10000 ; i++){
       sum = sum + 0.1;
      }
    WScript.Echo(sum);
    BigDecimal support for JavaScript [stz-ida.de]とか、JScript 8.0 [microsoft.com]とか知りません><
    • ASPでJScript
      =1000.00000000016

      <% @ Language="JScript" %>
      <%
      var sum = 0;
      for (var i=0 ; i < 10000 ; i++){
        sum = sum + 0.1;
      }
      Response.write(sum);
      %>
      ASPでVBS
      =1000.00000000016

      <% @ Language="VBScript" %>
      <%
      for i=1 to 10000
              temp = temp + 0.1
      next
      response.write temp
      %>
      ie6でJScript(明示)
      =1000.0000000001588

      <script language="JScript">
      var sum = 0;
      for (var i=0 ; i < 10000 ; i++){
        sum = sum + 0.1;
      }
      alert(sum); //docuent.write(sum);
      </script>
      ie6でVBS
      =1000.00000000016

      <script language="VBScript">
      for i=1 to 10000
              temp = temp + 0.1
      next
      alert temp //document.write temp
      </script>
      VBSはサーバー ⇔ ブラウザ間で整合性がとれているけど、
      JScriptはブラウザ ⇔ ブラウザ間の整合性を重視してるから、
      ie上の精度だけ実装を変えている…という事ですね?わかりません><
      親コメント
  • ・Perlで何も考えずにやった場合

    my $n = 0;
    for ( my $i = 0;  $i < 10000; $i++ ) {
        $n += 0.1;
    }
     
    print $n;
    実行結果:

    C:\Users\hylom>perl test.pl
    1000.00000000016
    ・PerlでMath::BigFloatを使った場合

    use Math::BigFloat;
     
    my $n = Math::BigFloat->new("0");
     
    for ( my $i = 0;  $i < 10000; $i++ ) {
        $n += 0.1;
    }
     
    print $n;
    実行結果:

    C:\Users\hylom>perl test.pl
    1000
    Math::BigFloatを使うと、もちろん実行速度は結構落ちる。
  • by L.Entis (21733) on 2008年09月10日 19時40分 (#1418924) 日記
    パックBCDの加算も、コメント [srad.jp]で書いたコードにちょっと手を加えると出来ると思いますよ。
    処理は複雑になりますが、同じビット数で倍の桁数処理できるので、桁数あたりの演算速度は確実に速くなると思います。

typodupeerror

最初のバージョンは常に打ち捨てられる。

読み込み中...