From: "NARUSE, Yui" Date: 2010-03-24T02:55:54+09:00 Subject: [ruby-dev:40738] Re: [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように 成瀬です。 (2010/03/23 21:23), Tadayoshi Funaba wrote: >> String#to_f は従来から指数表記を許していたので、 >> String#hex などと使い分けている String#to_i 事情が違うと理解しています。 > > 指数表現があることは関係あるんですかね。 > > to_i では 0x をデファオルトでは数値として見ない、そして to_i はオプショ > ンを受け付けるということ。もしこれがあまり意味のないことだったら、to_f > というより to_i の仕様に疑問が生じます。hex は関係なく、'0xff'.to_i は > 0 としかならないことに意味はないのか、ということです。意味のない使い分 > けと断じていいですか。 to_i がデフォルトで prefix を見ないのは、0377 のような、 0 詰めした数値文字列を、8 進数表記として解釈してしまうのを 問題視したからだと思っています。 今回の to_f は to_i と異なり、このような意図に反した解釈をしやすい パターンが無いので、やはり事情が異なると思います。 >> この提案では保守的に受け付ける範囲を狭めにしていました。 >> C99 の strtod と同等にするという案もあると思いますし、 >> わたしはそれに反対しません。 > > それが保守的だとは思わないですが、現状のものだったら、むしろ採用して欲 > しくないと思いました。 > > 成瀬さんに実は考えがあるという事なら他人に色々言われるのも嫌でしょうか > ら、一旦白紙に戻してやり直したほうがいいように思います。この中途半端提 > 案を採用することは反対です。 「保守的」である点についてはそこまでこだわりはないので、 実装するならば以下の通りでしょうか。 diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 9dd3ea9..c5b86fa 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1398,7 +1398,10 @@ class TestString < Test::Unit::TestCase assert_equal([-0.0].pack('G'), [S("-0.0").to_f].pack('G')) assert_equal([ 0.0].pack('G'), [S(" 0x0p+0").to_f].pack('G')) assert_equal([-0.0].pack('G'), [S("-0x0p+0").to_f].pack('G')) + assert_equal(255.0, S("0Xff").to_f) + assert_equal(255.5, S("0Xff.8").to_f) assert_equal(1.0, S("0X1.P+0").to_f) + assert_equal(1024.0, S("0x1p10").to_f) assert_equal(1024.0, S("0x1p+10").to_f) assert_equal(0.0009765625, S("0x1p-10").to_f) assert_equal(2.6881171418161356e+43, S("0x1.3494a9b171bf5p+144").to_f) diff --git a/util.c b/util.c index 9cdb563..eebc979 100644 --- a/util.c +++ b/util.c @@ -2110,6 +2110,8 @@ break2: static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; s0 = ++s; adj = 0; + nd = 0; + dsign = 0; while (*++s && (s1 = strchr(hexdigit, *s))) { adj *= 16; @@ -2124,21 +2126,18 @@ break2: } } - if (*s != 'P' && *s != 'p') { - s = s0; - goto ret; - } - - dsign = 0x2C - *++s; /* +: 2B, -: 2D */ - if (abs(dsign) != 1) { - s = s0; - goto ret; - } + if (*s == 'P' || *s == 'p') { + dsign = 0x2C - *++s; /* +: 2B, -: 2D */ + if (abs(dsign) != 1) { + dsign = 1; + s--; + } - for (nd = 0, s++; (c = *s) >= '0' && c <= '9'; s++) { - nd *= 10; - nd += c; - nd -= '0'; + while ((c = *++s) >= '0' && c <= '9') { + nd *= 10; + nd += c; + nd -= '0'; + } } dval(rv) = ldexp(adj, nd * dsign); -- NARUSE, Yui