えぐち@エスアンドイー です。

>>> In message [ruby-math:00059] Re: NaN again
    On Tue, 18 Jan 2000 13:12:08 +0900 (JST), gotoken / math.sci.hokudai.ac.jp (GOTO Kentaro) said:

ご> ごとけんです
ご> 
ご> In message "[ruby-math:00056] Re: NaN again"
ご>     on 00/01/18, EGUCHI Osamu <eguchi / shizuokanet.ne.jp> writes:

ご> >fl000118.rb でも "%+.1f" を使っていますが、libc の printf() が、
ご> >-0.0 を "+0.000000" と表示するバグを多くの処理系が持っていますので、
ご> >
ご> >--- fl000118.rb	Tue Jan 18 10:16:33 2000
ご> >+++ fl000118a.rb	Tue Jan 18 10:28:14 2000
ご> >@@ -18,8 +18,10 @@
ご> > 	    "+"
ご> > 	  elsif 0 > y
ご> > 	    "-"
ご> >-	  else
ご> >-	    "%+.1f" % y
ご> >+	  elsif 0.0 == y
ご> >+	    1.0 / y > 0.0 ? "+0.0" : "-0.0"
ご> >+	  else 
ご> >+	    "???"
ご> > 	  end
ご> > 	when FalseClass
ご> > 	  "F"
ご> >
ご> >とする必要があります。
ご> 
ご> これは、1.0/-Inf が正当なことを仮定しているので良くないのでは??
                ↑-0.0 ですね

それはたしかに、、

ご> [y].pack("G").unpack("B")[0][0] == ?0
ご> 
ご> くらいしか思い付きません。

MSB がセットされていない事を調べている、、のですよね。
pack/unpack って最後の手段的な感じですが、他にはどうも
方法が思い付かないです。(copysign() は ruby にないし、、)

ご> >NaN との比較は難物ですね、
ご> >わたしも現状の仕様である、「NaN との比較は偽」が自然だと思います。
ご> 
ご> FloatDomainError はどうでしょう??

特に問題はないと思いますが、
  NaN と何を比較しても不一致
と言う面白い性質を ruby で体験できなくなるとは言えます。
とはいえ <=> が NaN を伴った場合との不統一感は否めませんね。

どちらかと言うと、1.0 <=> NaN = NaN 説に傾きつつあります。
(1.0 - NaN = NaN からの類推、例外は発生しないと言う立場です)

ご> >BigFloat と Float に同等のテストを行った場合の結果の一致は、
ご> >誰もが期待する事だと思いますが、``Inf'' のテスト結果と言うのが
ご> >前述の±0の問題であるのなら、ruby の printf で対策するのが
ご> >妥当だと思います。(あと本来なら、printf(3) にも、、)
ご> 
ご> rb_f_sprintf() の修正はやったほうがほうが良さそうですね。

ちょっとパッチ作ってみました。

  % ./ruby -e 'p "%10.1E" % -0.0'
  "  -0.0E+00"

こんな事は出来ましたが、、

 + -0.0 の検出方法に問題を感じる
 + 元々ちゃんと -0.0 を表示できる場合も実行している
   (configure で検出すべき?)
 + -0.0 を -1.0 にすり替えて '1' => '0' なんてあんまりだ!

と言う種々の問題はあります。

	えぐち

Index: sprintf.c =================================================================== RCS file: /usr/home/eguchi/cvs.netlab.co.jp/ruby/sprintf.c,v retrieving revision 1.6 diff -d -u -r1.6 sprintf.c --- sprintf.c 2000/01/05 04:37:11 1.6 +++ sprintf.c 2000/01/18 06:00:31 @@ -632,7 +632,15 @@ need += 20; CHECK(need); - sprintf(&buf[blen], fbuf, fval); + if (fval == 0 && 1.0 / fval < 0.0) { + char* q; + sprintf(&buf[blen], fbuf, -1.0); + q = strchr(&buf[blen], '1'); + if (q) *q = '0'; + } + else { + sprintf(&buf[blen], fbuf, fval); + } blen += strlen(&buf[blen]); } break;