Project

General

Profile

Actions

Feature #2969

closed

String#to_f が -h.hhh±pd を解釈できるように

Added by naruse (Yui NARUSE) about 14 years ago. Updated almost 13 years ago.

Status:
Closed
Assignee:
-
Target version:
-

Description

=begin
C99 の printf には a という指定子があります。

  aA          The argument is printed in style ‘[-h.hhh±pd]’ where there is
              one digit before the hexadecimal point and the number after
              is equal to the precision specification for the argument;
              when the precision is missing, enough digits are produced to
              convey the argument's exact double-precision floating-point
              representation.  The values ∞ and NaN are printed as ‘inf’
              and ‘nan’, respectively.

これを使うと、以下のような形で整形されます。
-0.0 #=> "-0x0p+0"
729.0/10 #=> "0x1.239999999999ap+6"
Math.log(3) #=> "0x1.193ea7aad030ap+0"
Math.exp(100) #=> "0x1.3494a9b171bf5p+144"

この形式の利点は、複雑な浮動小数点数を比較的少ない文字数で正確に表せることと、
仮数部が16進であるため丸めが起きていることを説明する際に便利な点が挙げられます。

で、この形式を使っているのですが、RubyのString#to_f で解釈してくれず悲しくなるので、
解釈できるようにしませんか。
パッチは以下の通りです。

diff --git a/util.c b/util.c
index 5ebc5f3..e361d51 100644
--- a/util.c
+++ b/util.c
@@ -2106,6 +2106,44 @@ ruby_strtod(const char *s00, char **se)
}
break2:
if (*s == '0') {

  •   if (s[1] == 'x') {
    
  •       static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
    
  •       s0 = ++s;
    
  •       adj = 0;
    
  •       while (*++s && (s1 = strchr(hexdigit, *s))) {
    
  •           adj *= 16;
    
  •           adj += (s1 - hexdigit) & 15;
    
  •       }
    
  •       if (*s == '.') {
    
  •           aadj = 1.;
    
  •           while (*++s && (s1 = strchr(hexdigit, *s))) {
    
  •               aadj /= 16;
    
  •               adj += aadj * ((s1 - hexdigit) & 15);
    
  •           }
    
  •       }
    
  •       if (*s != 'p') {
    
  •           s = s0;
    
  •           goto ret;
    
  •       }
    
  •       dsign = 0x2C - *++s; /* +: 2B, -: 2D */
    
  •       if (abs(dsign) != 1) {
    
  •           s = s0;
    
  •           goto ret;
    
  •       }
    
  •       for (nd = 0, s++; (c = *s) >= '0' && c <= '9'; s++) {
    
  •           nd *= 10;
    
  •           nd += c;
    
  •           nd -= '0';
    
  •       }
    
  •       dval(rv) = ldexp(adj, nd * dsign);
    
  •       goto ret;
    
  •   }
       nz0 = 1;
       while (*++s == '0') ;
       if (!*s)
    

diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 64205f6..72d3242 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1381,10 +1381,24 @@ class TestString < Test::Unit::TestCase
end

def test_to_f
  • assert_equal(0.0, S("0.0").to_f)
  • assert_equal(?0, S("0.0").to_f.to_s[0])
  • assert_equal(-0.0, S("-0.0").to_f)
  • assert_equal(?-, S("-0.0").to_f.to_s[0])
    assert_equal(344.3, S("344.3").to_f)
    assert_equal(5.9742e24, S("5.9742e24").to_f)
    assert_equal(98.6, S("98.6 degrees").to_f)
    assert_equal(0.0, S("degrees 100.0").to_f)
  • assert_equal(0.0, S("0x0p+0").to_f)
  • assert_equal(?0, S("0x0p+0").to_f.to_s[0])
  • assert_equal(-0.0, S("-0x0p+0").to_f)
  • assert_equal(?-, S("-0x0p+0").to_f.to_s[0])
  • assert_equal(1.0, S("0x1p+0").to_f)
  • assert_equal(?1, S("0x1p+0").to_f.to_s[0])
  • 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)
  • assert_equal(-3.720075976020836e-44, S("-0x1.a8c1f14e2af5dp-145").to_f)
    end
def test_to_i

=end

Actions #1

Updated by mrkn (Kenta Murata) about 14 years ago

=begin
村田です。

On 2010/03/16, at 4:01, Yui NARUSE wrote:

C99 の printf には a という指定子があります。

(snip)

この形式の利点は、複雑な浮動小数点数を比較的少ない文字数で正確に表せることと、
仮数部が16進であるため丸めが起きていることを説明する際に便利な点が挙げられます。

で、この形式を使っているのですが、RubyのString#to_f で解釈してくれず悲しくなるので、
解釈できるようにしませんか。

この機能、私も欲しいです。

--
Kenta Murata
OpenPGP FP = FA26 35D7 4F98 3498 0810 E0D5 F213 966F E9EB 0BCC

本を書きました!!
『Ruby 逆引きレシピ』 http://www.amazon.co.jp/dp/4798119881/mrkn-22

E-mail:
twitter: http://twitter.com/mrkn/
blog: http://d.hatena.ne.jp/mrkn/

=end

Actions #2

Updated by naruse (Yui NARUSE) about 14 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r26965.
Yui, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Actions #3

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin
質問ですが、この形式は入力だけでなく、なんらかの方法で出力でも利用でき
るのでしょうか。

あと、これを浮動小数点数において16進数を受けつけるようにした、と解釈す
ると、たとえば、Integer では、

Integer('0xff') #=> 255
'0xff'.to_i #=> 0

という違いがあるようです。

Float('0xff.0p+0') #=> 255.0
'0xff.0p+0'.to_f #=> 255.0

それから、この形式がとても硬直しているように感じます。この形式は e を共
なう指数表記と似ていると思うのですが、1e1 と書けても、0x1p1 とは書けな
いし、0xff、0xff.0 なども受けつけないということですよね。

=end

Actions #4

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(2010/03/22 22:08), Tadayoshi Funaba wrote:

質問ですが、この形式は入力だけでなく、なんらかの方法で出力でも利用でき
るのでしょうか。

sprintf フォーマットに %a と %A を追加する提案を予定しています。
(つまり、String#% にも追加される)

ただ、現状 missing/vsnprintf.c が %a %A に対応しておらず、
実装に時間がかかりそうだったので入力だけ先に提案しました。

1.9.3 ではこちらも入れたいと思っています。

あと、これを浮動小数点数において16進数を受けつけるようにした、と解釈す
ると、たとえば、Integer では、

Integer('0xff') #=> 255
'0xff'.to_i #=> 0

という違いがあるようです。

String#to_f は従来から指数表記を許していたので、
String#hex などと使い分けている String#to_i 事情が違うと理解しています。

Float('0xff.0p+0') #=> 255.0
'0xff.0p+0'.to_f #=> 255.0

それから、この形式がとても硬直しているように感じます。この形式は e を共
なう指数表記と似ていると思うのですが、1e1 と書けても、0x1p1 とは書けな
いし、0xff、0xff.0 なども受けつけないということですよね。

この提案では保守的に受け付ける範囲を狭めにしていました。
C99 の strtod と同等にするという案もあると思いますし、
わたしはそれに反対しません。

--
NARUSE, Yui

=end

Actions #5

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

String#to_f は従来から指数表記を許していたので、
String#hex などと使い分けている String#to_i 事情が違うと理解しています。

指数表現があることは関係あるんですかね。

to_i では 0x をデファオルトでは数値として見ない、そして to_i はオプショ
ンを受け付けるということ。もしこれがあまり意味のないことだったら、to_f
というより to_i の仕様に疑問が生じます。hex は関係なく、'0xff'.to_i は
0 としかならないことに意味はないのか、ということです。意味のない使い分
けと断じていいですか。

この提案では保守的に受け付ける範囲を狭めにしていました。
C99 の strtod と同等にするという案もあると思いますし、
わたしはそれに反対しません。

それが保守的だとは思わないですが、現状のものだったら、むしろ採用して欲
しくないと思いました。

成瀬さんに実は考えがあるという事なら他人に色々言われるのも嫌でしょうか
ら、一旦白紙に戻してやり直したほうがいいように思います。この中途半端提
案を採用することは反対です。

=end

Actions #6

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(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

=end

Actions #7

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

to_i がデフォルトで prefix を見ないのは、0377 のような、
0 詰めした数値文字列を、8 進数表記として解釈してしまうのを
問題視したからだと思っています。

今回の to_f は to_i と異なり、このような意図に反した解釈をしやすい
パターンが無いので、やはり事情が異なると思います。

そうなのかもしれないけど、浮動小数点数にも16進数表記がある、という時点
でもう基本的条件は同じになったと考えたほうがいいと思います。

しかし、2進や8進も含むものとして打ち出せなかったところが提案がかなり微
妙であることを示しているように感じます。こういう例外的な対応を取り入れ
るのはすっきりしません。

printf の対になるものは scanf なので、lib/scanf.rb で対応するくらいで十
分という気がします。

printf の変更を考えてるなら、それを仕様と実装が用意出来てからでもいいわ
けだし、今すぐ採用する必要はないと思います。

=end

Actions #8

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(2010/03/24 23:34), Tadayoshi Funaba wrote:

to_i がデフォルトで prefix を見ないのは、0377 のような、
0 詰めした数値文字列を、8 進数表記として解釈してしまうのを
問題視したからだと思っています。

今回の to_f は to_i と異なり、このような意図に反した解釈をしやすい
パターンが無いので、やはり事情が異なると思います。

そうなのかもしれないけど、浮動小数点数にも16進数表記がある、という時点
でもう基本的条件は同じになったと考えたほうがいいと思います。

String#to_i は 0-prefix での 8 進数誤爆を防ぐために分けたのだと
思っているわけですが、String#to_f は何のために分けるんですか?
必要性があれば分けた方がいいのでしょうが、あるようには思えません。

しかし、2進や8進も含むものとして打ち出せなかったところが提案がかなり微
妙であることを示しているように感じます。こういう例外的な対応を取り入れ
るのはすっきりしません。

先のパッチの対象関数が ruby_strtod である通り、
先の提案は strtod(3) をベースにしています。
よって、そこにない 2 進や 8 進を独自に追加する必要を感じません。

printf の対になるものは scanf なので、lib/scanf.rb で対応するくらいで十
分という気がします。

scanf も hexadecimal-floating-constant に対応してもいいとは思いますが、
そもそもが C99 のリテラルなので、printf にこだわることも無いと思います。

printf の変更を考えてるなら、それを仕様と実装が用意出来てからでもいいわ
けだし、今すぐ採用する必要はないと思います。

missing/vsnprintf.c 以外ならば、以下の通りです。
Windows 以外ならばこれで試すことはできるでしょう。

diff --git a/sprintf.c b/sprintf.c
index bec0569..e26b833 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -227,6 +227,10 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

  •        | equal to the precision, or in dd.dddd form otherwise.
    
  •        | The precision specifies the number of significant digits.
    
  •    G   | Equivalent to `g', but use an uppercase `E' in exponent form.
    
    •    a   | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
      
    •        | which is consisted from optional sign, "0x", fraction part
      
    •        | as hexadecimal, "p", and exponential part as decimal.
      
    •    A   | Equivalent to `a', but use uppercase `X' and `P'.
      
    •  Field |  Other Format
      
    •  ------+--------------------------------------------------------------
      

@@ -244,7 +248,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

  • Flag | Applies to | Meaning
  • ---------+---------------+-----------------------------------------
  • space | bBdiouxX | Leave a space at the start of
    •         | eEfgG         | non-negative numbers.
      
    •         | aAeEfgG       | non-negative numbers.
      
    •         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
      
    •         |               | a minus sign with absolute value for
      
    •         |               | negative values.
      

@@ -255,19 +259,19 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

  •         |               | sprintf string.
    
  • ---------+---------------+-----------------------------------------
  • #       | bBoxX         | Use an alternative format.
    
    •         | eEfgG         | For the conversions `o', increase the precision
      
    •         | aAeEfgG       | For the conversions `o', increase the precision
      
    •         |               | until the first digit will be `0' if
      
    •         |               | it is not formatted as complements.
      
    •         |               | For the conversions `x', `X', `b' and `B'
      
    •         |               | on non-zero, prefix the result with ``0x'',
      
    •         |               | ``0X'', ``0b'' and ``0B'', respectively.
      
    •         |               | For `e', `E', `f', `g', and 'G',
      
    •         |               | For `a', `A', `e', `E', `f', `g', and 'G',
      
    •         |               | force a decimal point to be added,
      
    •         |               | even if no digits follow.
      
    •         |               | For `g' and 'G', do not remove trailing zeros.
      
    • ---------+---------------+-----------------------------------------
      •    | bBdiouxX      | Add a leading plus sign to non-negative
        
    •         | eEfgG         | numbers.
      
    •         | aAeEfgG       | numbers.
      
    •         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
      
    •         |               | a minus sign with absolute value for
      
    •         |               | negative values.
      

@@ -275,7 +279,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

    •    | all           | Left-justify the result of this conversion.
      
  • ---------+---------------+-----------------------------------------
  • 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
    •         | eEfgG         | For `o', `x', `X', `b' and `B', radix-1
      
    •         | aAeEfgG       | For `o', `x', `X', `b' and `B', radix-1
      
    •         | (numeric fmt) | is used for negative numbers formatted as
      
    •         |               | complements.
      
    • ---------+---------------+-----------------------------------------
      @@ -983,6 +987,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
      case 'G':
      case 'e':
      case 'E':
  • case 'a':
  • case 'A':
    {
    VALUE val = GETARG();
    double fval;

--
NARUSE, Yui

=end

Actions #9

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

先のパッチの対象関数が ruby_strtod である通り、
先の提案は strtod(3) をベースにしています。
よって、そこにない 2 進や 8 進を独自に追加する必要を感じません。

意味がわかりません。でも、その必要を感じの中にこの提案も含まれていると
いうことだと思います。全く必要ないとはいいませんが、あまり必要でないと
思います。

scanf も hexadecimal-floating-constant に対応してもいいとは思いますが、
そもそもが C99 のリテラルなので、printf にこだわることも無いと思います。

じゃ、この提案自体必要なかったんじゃないかな。中途半端に Float を弄るの
は止めたほうがいいと思います。

=end

Actions #10

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(2010/03/25 2:51), Tadayoshi Funaba wrote:

先のパッチの対象関数が ruby_strtod である通り、
先の提案は strtod(3) をベースにしています。
よって、そこにない 2 進や 8 進を独自に追加する必要を感じません。

意味がわかりません。でも、その必要を感じの中にこの提案も含まれていると
いうことだと思います。全く必要ないとはいいませんが、あまり必要でないと
思います。

strtod(3) の解釈対象に含まれていない 2 進や 8 進を否定することが、
なぜ含まれている 16 進の否定につながるのでしょう。

scanf も hexadecimal-floating-constant に対応してもいいとは思いますが、
そもそもが C99 のリテラルなので、printf にこだわることも無いと思います。

じゃ、この提案自体必要なかったんじゃないかな。中途半端に Float を弄るの
は止めたほうがいいと思います。

String#to_f の仕様・実装が下敷きとしていると思われる
strtod(3) の要素を 1 つマージすると言うことが中途半端だとは思いません。

--
NARUSE, Yui

=end

Actions #11

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

strtod(3) の解釈対象に含まれていない 2 進や 8 進を否定することが、
なぜ含まれている 16 進の否定につながるのでしょう。

これは to_f (と Float()) の話で、strtod(3) の話ではありません。成瀬さん
が認めたように、2進数も8進数もさほど重要だとは思われていなくて、今回の
提案にある浮動小数点数のための拡張された16進数形式も同じだということだ
と思います。

String#to_f の仕様・実装が下敷きとしていると思われる
strtod(3) の要素を 1 つマージすると言うことが中途半端だとは思いません。

strtod(3) に多少影響を受けていることはあるかもしれませんが、一番考慮さ
れているのは ruby での常識、ruby のリテラルだと思います。

言われることは、Float#strtod であるなら理由として成り立ちますが、利用者
が、strtod と同じであることを求めてるわけはないと思います。

また、結果的に他所の仕様が影響を与えることはよくあることですが、to_f が
strtod に従わなければならない理由にはならないと思いますよ。

「何故そうしたのか良くわからない、ああそうか、strtod(3) を参考にしたか
らこうなっているのか」「何故こうなっているの? -- それは strtod(3) と同
じものを提供しようとしたからです」そういう事なら分りますが、そういう話
じゃないですよね。

lib/scanf.rb で提供するほうが相応わしいと思います。

=end

Actions #12

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/26 3:05), Tadayoshi Funaba wrote:

strtod(3) の解釈対象に含まれていない 2 進や 8 進を否定することが、
なぜ含まれている 16 進の否定につながるのでしょう。

これは to_f (と Float()) の話で、strtod(3) の話ではありません。成瀬さん
が認めたように、2進数も8進数もさほど重要だとは思われていなくて、今回の
提案にある浮動小数点数のための拡張された16進数形式も同じだということだ
と思います。

なぜ同じなのでしょう。
現在サポートしていないのは単に実装時期の問題だと思っているのですが。

String#to_f の仕様・実装が下敷きとしていると思われる
strtod(3) の要素を 1 つマージすると言うことが中途半端だとは思いません。

strtod(3) に多少影響を受けていることはあるかもしれませんが、一番考慮さ
れているのは ruby での常識、ruby のリテラルだと思います。

Ruby のリテラルは C 言語由来と思われるので、
これもやはり外しているとは思いません。
それとも、先に Ruby リテラルにこの形式を入れるべきという主張ですか?

言われることは、Float#strtod であるなら理由として成り立ちますが、利用者
が、strtod と同じであることを求めてるわけはないと思います。

また、結果的に他所の仕様が影響を与えることはよくあることですが、to_f が
strtod に従わなければならない理由にはならないと思いますよ。

全面的に strtod(3) に従うべきという主張はわたしもしません。
一方で、strtod(3) で解釈できるものは to_f でも解釈できていいだろうという
主張はありえ、

「何故そうしたのか良くわからない、ああそうか、strtod(3) を参考にしたか
らこうなっているのか」「何故こうなっているの? -- それは strtod(3) と同
じものを提供しようとしたからです」そういう事なら分りますが、そういう話
じゃないですよね。

わたしの意図という話でしたら「同じものを提供しよう」とまでは言いませんが、
「参考に」はしています。

Ruby の仕様・実装という意味でしたら、r2457 からするに、
「同じものを提供しようとした」ように見えます。
ここで 16 進記法を解釈しなくなったのは、現状 "INF" や "NAN" なども
解釈しないことを考えると、C89 の strtod が由来だからでしょうかね。
この点はまつもとさんに確認を取ります。

 * util.c (ruby_strtod): use own strtod(3) implementation to avoid
   locale hell.  Due to this change "0xff".to_f no longer returns 255.0

lib/scanf.rb で提供するほうが相応わしいと思います。

わたしは String#to_f は解釈すべきだと思っています。

--
NARUSE, Yui

=end

Actions #13

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

なぜ同じなのでしょう。
現在サポートしていないのは単に実装時期の問題だと思っているのですが。

同じというよりは、もっと低いですかね。

Ruby のリテラルは C 言語由来と思われるので、
これもやはり外しているとは思いません。
それとも、先に Ruby リテラルにこの形式を入れるべきという主張ですか?

それはよくわかりません。perl 経由のような気もします。仮に別にそうであっ
ても、C に従わなければならないこともないでしょう。

2進数や8進数も含めてそれが有用だから16進もある、場合によってはリテラル
もそうする、というなら Float() の仕様として個人的に納得できます。それは
そうですが、そうすべきだという主張ではありません。

そうでないなら、lib/scanf.rb でいいと思います。

Ruby の仕様・実装という意味でしたら、r2457 からするに、
「同じものを提供しようとした」ように見えます。
ここで 16 進記法を解釈しなくなったのは、現状 "INF" や "NAN" なども
解釈しないことを考えると、C89 の strtod が由来だからでしょうかね。
この点はまつもとさんに確認を取ります。

権威主義者でもないし、C やまつもとさんに忠誠を誓っているわけでもないの
で、別にそれで考えが変るわけじゃないんですよ。そりゃ、いろいろ言っても
まつもとさんの考えで決るとは思いますが。

strtod(3) を参考にしたり、影響されたりすることは普通にあるとは思います
が、strtod をこれ程までに尊敬している人は初めてです。

=end

Actions #14

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(2010/03/26 8:20), EGUCHI Osamu wrote:

えぐち@エスアンドイーです
#おひさしぶりです

2010年3月24日2:55 NARUSE, Yui:

(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 と異なり、このような意図に反した解釈をしやすい
パターンが無いので、やはり事情が異なると思います。

作為的ですが
0x1.badp+0
のようなパターンで意図に反した解釈をする可能性があります。

過去に16進浮動小数点を検討したときに
このようなメソッドとの曖昧性で断念した記憶があります。

リテラルの場合は確かにご指摘の通りです。
なので、Ruby で 16 進浮動小数点数リテラルを導入するのは困難ですね。

to_f の場合には、"0x1" を 0 と解釈して欲しかった例と
同程度には少ないと思っています。

--
NARUSE, Yui

=end

Actions #15

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/26 4:02), Tadayoshi Funaba wrote:

なぜ同じなのでしょう。
現在サポートしていないのは単に実装時期の問題だと思っているのですが。

同じというよりは、もっと低いですかね。

Ruby のリテラルは C 言語由来と思われるので、
これもやはり外しているとは思いません。
それとも、先に Ruby リテラルにこの形式を入れるべきという主張ですか?

それはよくわかりません。perl 経由のような気もします。仮に別にそうであっ
ても、C に従わなければならないこともないでしょう。

2進数や8進数も含めてそれが有用だから16進もある、場合によってはリテラル
もそうする、というなら Float() の仕様として個人的に納得できます。それは
そうですが、そうすべきだという主張ではありません。

つまり、ふなばさんは 16 進よりも 2 進や 8 進形式が好みであるところ、
16 進がそれらを差し置いて入るのは納得できないという事でしょうか。

Ruby の仕様・実装という意味でしたら、r2457 からするに、
「同じものを提供しようとした」ように見えます。
ここで 16 進記法を解釈しなくなったのは、現状 "INF" や "NAN" なども
解釈しないことを考えると、C89 の strtod が由来だからでしょうかね。
この点はまつもとさんに確認を取ります。

権威主義者でもないし、C やまつもとさんに忠誠を誓っているわけでもないの
で、別にそれで考えが変るわけじゃないんですよ。そりゃ、いろいろ言っても
まつもとさんの考えで決るとは思いますが。

strtod(3) を参考にしたり、影響されたりすることは普通にあるとは思います
が、strtod をこれ程までに尊敬している人は初めてです。

わたしの主張は、以下のようなものです。
(1) -h.hhh±pd 形式は、符号・仮数・指数という浮動小数点数をそのまま表しているため、
浮動小数点の内容を知るのに有用である
(2) -h.hhh±pd 形式は、C99 の浮動小数点数リテラルの一形式であり、
その形式は文法に、出力は printf に、解釈は strtod に記述されている
(3) 有用かつ安定した形式なので Ruby でも扱えるべきだ

--
NARUSE, Yui

=end

Actions #16

Updated by kosaki (Motohiro KOSAKI) about 14 years ago

=begin

strtod(3) を参考にしたり、影響されたりすることは普通にあるとは思います
が、strtod をこれ程までに尊敬している人は初めてです。

わたしの主張は、以下のようなものです。
(1) -h.hhh±pd 形式は、符号・仮数・指数という浮動小数点数をそのまま表しているため、
浮動小数点の内容を知るのに有用である
(2) -h.hhh±pd 形式は、C99 の浮動小数点数リテラルの一形式であり、
その形式は文法に、出力は printf に、解釈は strtod に記述されている
(3) 有用かつ安定した形式なので Ruby でも扱えるべきだ

kosakiです

えぐちさんの提示された 0x1.badp+0
については見解を提示してもらえませんでしょうか。有用なのは認めますが、非常にマイナーな表記形式であり、導入しても使用ユーザは小数にとどまると考えています。もっというと、うれしいのは一般ユーザじゃなくて見当違いのバグ報告にたいしてwont
fix といいやすくなるのが最大のメリットに見えます。

よって副作用があるなら lib/scanf.rb
に格下げというのは、ある意味現実的な判断のようにも思えます。これについて、どう判断しているのかを教えて欲しいです。

ふなばさんのメールについては趣旨が十分整理されていないように感じるので、賛成も反対も差し控えます。

=end

Actions #17

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/27 18:19), KOSAKI Motohiro wrote:

strtod(3) を参考にしたり、影響されたりすることは普通にあるとは思います
が、strtod をこれ程までに尊敬している人は初めてです。

わたしの主張は、以下のようなものです。
(1) -h.hhh±pd 形式は、符号・仮数・指数という浮動小数点数をそのまま表しているため、
浮動小数点の内容を知るのに有用である
(2) -h.hhh±pd 形式は、C99 の浮動小数点数リテラルの一形式であり、
その形式は文法に、出力は printf に、解釈は strtod に記述されている
(3) 有用かつ安定した形式なので Ruby でも扱えるべきだ

kosakiです

えぐちさんの提示された 0x1.badp+0
については見解を提示してもらえませんでしょうか。有用なのは認めますが、
非常にマイナーな表記形式であり、導入しても使用ユーザは小数にとどまると考えています。
もっというと、うれしいのは一般ユーザじゃなくて見当違いのバグ報告にたいしてwont
fix といいやすくなるのが最大のメリットに見えます。

よって副作用があるなら lib/scanf.rb
に格下げというのは、ある意味現実的な判断のようにも思えます。
これについて、どう判断しているのかを教えて欲しいです。

ML 上での最大の use case は浮動小数点数を理解していないユーザへの説明用でしょうね。

さて、えぐちさんの指摘は第一にはリテラルとしての導入は不可能という指摘だと思います。
それは仰るとおりです。

一方で、String#to_f との衝突で考えると、例えば "0x1.badp+0".to_f を実行した
場合の結果は何を期待しているのでしょうか。
たぶん 0x1 を解釈して 1.0 が返るのを期待するのかなと思います。
しかし、String#to_f は 16 進を解さないので、現在 0.0 が返ります。
つまり、元々期待はずれだった結果がまた別の値になるわけです。
これは、当初の期待が誤っていると言えるでしょう。
よって、String#to_f についてはえぐちさんの指摘は当たらないと考えます。

--
NARUSE, Yui

=end

Actions #18

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

つまり、ふなばさんは 16 進よりも 2 進や 8 進形式が好みであるところ、
16 進がそれらを差し置いて入るのは納得できないという事でしょうか。

統一性とバランスの問題です。

わたしの主張は、以下のようなものです。
(1) -h.hhh±pd 形式は、符号・仮数・指数という浮動小数点数をそのまま表しているため、
浮動小数点の内容を知るのに有用である
(2) -h.hhh±pd 形式は、C99 の浮動小数点数リテラルの一形式であり、
その形式は文法に、出力は printf に、解釈は strtod に記述されている
(3) 有用かつ安定した形式なので Ruby でも扱えるべきだ

ruby は C じゃないんで、直ちに ruby で採用しなければということにはらな
いでしょう。しかし、ruby でつかえてもいいと思います。で、一応 scanf と
いう対案を出しています。しかし、これまで strtod がどうのという話を繰り
返し、無視されている状態です。

成瀬さんは ruby と strtod の経緯を極めて自分の都合のようように捉えてい
るようです。僕も真相は知りませんが、普通に考えたら、

初期において strtod は ruby の要求に合致していた。だが、いつしか
strtod が変化し始めた。自前の strtod を得ると例外なく16進数は扱えなくなっ
たが、使えていた事はむしろ予想外だったので、躊躇うこともなかった。

という事なのでは。

どっちにしろ、strtod はどうでもいいと思うのですが。

成瀬さんのほうは、これは正統な進化だからケチをつけられる筋合いはないと
いう一点張りのようで、簡単には決着がつないだろうから、すでにリポジトリ
で変更されている分は一旦戻させて貰おうと思います (バグもあるようだし)。
ご了承下さい。

=end

Actions #19

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/27 20:26), EGUCHI Osamu wrote:

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

2010年3月27日19:14 NARUSE, Yui:

さて、えぐちさんの指摘は第一にはリテラルとしての導入は不可能という指摘だと思います。
それは仰るとおりです。

リテラル表現には(そのままの)aA 表現は導入不可能という点には
異論はないという共通認識を踏まえた上で。。

一方で、String#to_f との衝突で考えると、例えば "0x1.badp+0".to_f を実行した
場合の結果は何を期待しているのでしょうか。
たぶん 0x1 を解釈して 1.0 が返るのを期待するのかなと思います。
しかし、String#to_f は 16 進を解さないので、現在 0.0 が返ります。
つまり、元々期待はずれだった結果がまた別の値になるわけです。
これは、当初の期待が誤っていると言えるでしょう。
よって、String#to_f についてはえぐちさんの指摘は当たらないと考えます。

String#to_f については '.’ + メソッド との整合性は必須でないので、
上記の論点は正しいと思います。

ただ、浮動小数点リテラル表現と String#to_f は同じであろうと
期待するのはかなり自然なことではないかと思います。
#驚き最小の法則

こちらは、一貫性と利便性が衝突する事例という話だと思います。

で、現在同じかというと "10".to_f のような 10 進整数はすでに異なっています。
また、エッジケースを攻めると 4._9 はエラーになるが、
"4._9".to_f は 4.9 を返すというような例もあります。

結局、制約の強いリテラルと、文字列を解釈するのでは条件が異なるわけで、
「Ruby のリテラルとして浮動小数点数として解釈されるならば、
String#to_f でも解釈されるべき」は尊重されるべきだと思いますが、
その逆は必ずしも成り立つ必要はないと思います。

--
NARUSE, Yui

=end

Actions #20

Updated by kosaki (Motohiro KOSAKI) about 14 years ago

=begin

つまり、ふなばさんは 16 進よりも 2 進や 8 進形式が好みであるところ、
16 進がそれらを差し置いて入るのは納得できないという事でしょうか。

統一性とバランスの問題です。

これだけだと「直感的に気に入らない。」としか読めないのでなんとか言語化してもらえませんか。
今のところふなばさんの意見に賛成する理由はないというか、そもそも意図が
明白ではないように見えているので、現時点でのrevertには反対です。

ちゃんと議論しておかないと、再提案の時に同じ話を蒸し返すことになって
お互い嫌な思いをするのではないでしょうか。

成瀬さんのほうは、これは正統な進化だからケチをつけられる筋合いはないと
いう一点張りのようで、

ここは賛成しません。
安定している形式であると考える根拠、有用と考える根拠は書かれているように読めます。
それに賛成するかどうかはともかく、一点張りとは思いません。

私から見ると成瀬さんの意見は「賛成できないけどいいたいことは分かる。」ですが
ふなばさんのメールはそもそも言いたい事がよく分からないので返信が書きにくいです。

=end

Actions #21

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/27 20:56), Tadayoshi Funaba wrote:

つまり、ふなばさんは 16 進よりも 2 進や 8 進形式が好みであるところ、
16 進がそれらを差し置いて入るのは納得できないという事でしょうか。

統一性とバランスの問題です。

何の統一性とバランスでしょう。
String#to_i との統一性とバランス、でしょうか。

わたしの主張は、以下のようなものです。
(1) -h.hhh±pd 形式は、符号・仮数・指数という浮動小数点数をそのまま表しているため、
浮動小数点の内容を知るのに有用である
(2) -h.hhh±pd 形式は、C99 の浮動小数点数リテラルの一形式であり、
その形式は文法に、出力は printf に、解釈は strtod に記述されている
(3) 有用かつ安定した形式なので Ruby でも扱えるべきだ

ruby は C じゃないんで、直ちに ruby で採用しなければということにはらな
いでしょう。しかし、ruby でつかえてもいいと思います。で、一応 scanf と
いう対案を出しています。しかし、これまで strtod がどうのという話を繰り
返し、無視されている状態です。

strtod(3) の話は、16進整数表現の解釈はできないのかとの問いに対して、
strtod(3) の範囲ならば矛盾無く拡張できると返したのが最初です。

また、printf の反対なのだから scanf で対応するべきという主張に対しては、
16進浮動小数点数形式も浮動小数点数形式なので printf との対応にこだわらず、
String#to_f でも扱えていいと思うと返しています。

なお、先に scanf 側にも実装するべきとの主張ならばそうかもしれません。
と、思って lib/scanf.rb を見ると……、

def extract_float(s); s.to_f if s &&! skip; end

えーっと、lib/scanf.rb で使うというユースケースを String#to_f に
追加していいですか。
とりあえず Ruby で実装するなら以下の通りでしょうか。

diff --git a/lib/scanf.rb b/lib/scanf.rb
index ffc0d90..dd6ba6c 100644
--- a/lib/scanf.rb
+++ b/lib/scanf.rb
@@ -112,7 +112,7 @@ and tests/scanftests.rb for examples.)
[x,X]
Matches an optionally signed hexadecimal integer,

-[f,g,e,E]
+[a,e,f,g,A,E,F,G]
Matches an optionally signed floating-point number.

[s]
@@ -309,7 +309,22 @@ module Scanf

  def skip;  /^\s*%\*/.match(@spec_string); end
  • def extract_float(s); s.to_f if s &&! skip; end
  • def extract_float(s)

  •  return nil unless s &&! skip
    
  •  if /\A(?<sign>[-+]?)0[xX](?<frac>\.\h+|\h+(?:\.\h*)?)[pP](?<exp>[-+]\d+)/ =~ s
    
  •    f1, f2 = frac.split('.')
    
  •    f = f1.hex
    
  •    if f2
    
  •      len = f2.length
    
  •      if len > 0
    
  •        f += f2.hex / (16.0 ** len)
    
  •      end
    
  •    end
    
  •    (sign == ?- ? -1 : 1) * Math.ldexp(f, exp.to_i)
    
  •  else
    
  •    s.to_f
    
  •  end
    
  • end
    def extract_decimal(s); s.to_i if s &&! skip; end
    def extract_hex(s); s.hex if s &&! skip; end
    def extract_octal(s); s.oct if s &&! skip; end
    @@ -409,12 +424,12 @@ module Scanf
    [ "([-+][0-7]{1,#{$1.to_i-1}}|[0-7]{1,#{$1}})", :extract_octal ]

      # %f
    
  •    when /%\*?[efgEFG]/
    
  •      [ '([-+]?(?:\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))', :extract_float ]
    
  •    when /%\*?[aefgAEFG]/
    
  •      [ '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))', :extract_float ]
    
         # %5f
    
  •    when /%\*?(\d+)[efgEFG]/
    
  •      [ '(?=[-+]?(?:\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))' +
    
  •    when /%\*?(\d+)[aefgAEFG]/
    
  •      [ '(?=[-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))' +
           "(\\S{1,#{$1}})", :extract_float ]
    
         # %5s
    

@@ -491,7 +506,7 @@ module Scanf
attr_reader :string_left, :last_spec_tried,
:last_match_tried, :matched_count, :space

  • SPECIFIERS = 'diuXxofFeEgGsc'
  • SPECIFIERS = 'diuXxofFeEgGscaA'
    REGEX = /
    # possible space, followed by...
    (?:\s*
    diff --git a/test/scanf/test_scanf.rb b/test/scanf/test_scanf.rb
    index 2ec4e54..169ffe6 100644
    --- a/test/scanf/test_scanf.rb
    +++ b/test/scanf/test_scanf.rb
    @@ -276,6 +276,8 @@ module ScanfTests
    [ "%g", "+3.25", [3.25] ],
    [ "%G", "+3.25e2", [325.0] ],
    [ "%f", "3.z", [3.0] ],
  •  [ "%a", "0X1P+10", [1024.0] ],
    
  •  [ "%A", "0x1.deadbeefp+99", [1.1851510441583988e+30] ],
    

Testing embedded matches including literal '[' behavior

    [",%d,%f", ",10,1.1", [10,1.1] ],

--
NARUSE, Yui

=end

Actions #22

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/27 21:46), EGUCHI Osamu wrote:

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

2010年3月27日21:01 NARUSE, Yui:

(2010/03/27 20:26), EGUCHI Osamu wrote:

2010年3月27日19:14 NARUSE, Yui:

よって、String#to_f についてはえぐちさんの指摘は当たらないと考えます。
String#to_f については '.’ + メソッド との整合性は必須でないので、
上記の論点は正しいと思います。

ただ、浮動小数点リテラル表現と String#to_f は同じであろうと
期待するのはかなり自然なことではないかと思います。
#驚き最小の法則

こちらは、一貫性と利便性が衝突する事例という話だと思います。

で、現在同じかというと "10".to_f のような 10 進整数はすでに異なっています。
また、エッジケースを攻めると 4._9 はエラーになるが、
"4._9".to_f は 4.9 を返すというような例もあります。

この挙動は厄介です。

Float(”4._9”) ではまた別のエラーになったりします。
どうあるべきだったのかについては明確な論点を持ってません。
ただ、小数点とメソッド呼び出しが曖昧になるケースという意味で
今回の議論と同根だと思います。

結局、制約の強いリテラルと、文字列を解釈するのでは条件が異なるわけで、
「Ruby のリテラルとして浮動小数点数として解釈されるならば、
String#to_f でも解釈されるべき」は尊重されるべきだと思いますが、
その逆は必ずしも成り立つ必要はないと思います。

それも踏まえて、、

Rubyリテラル表現としても使える表現形式を模索してからでも
遅くないように思えます。

踏まえるとなぜRubyリテラル表現としても使える表現形式を模索することに
なるのかがよくわかりません。

推測するに、前段とは独立に、よりよい形式が現れた際に今回の形式との互換性に
縛られることを懸念しているのではないかと思います。

で、mame さんに教えてもらったのですが、IEEE 754:2008 の draft に、
今回の形式と浮動小数点数との変換を求める規定があるそうです。

7.12.2 External hexadecimal character sequences representing finite numbers

Implementations supporting binary formats shall provide conversions between all
supported internal binary formats and external hexadecimal character sequences.
External hexadecimal character sequences for finite numbers are of the form
specified by ISO/IEC 9899, Programming Languages – C (C99) subclauses:
  6.4.4.2 floating constants,
  20.1.3 strtod,
  7.19.6.2 fscanf (a, e, f, g), and
  7.19.6.1 fprintf (a, A).

IEEE 754:2008 draft 1.2.9, 27 January 2007
http://www.validlab.com/754R/nonabelian.com/754/comments/Q754.129.pdf

Ruby は IEEE 754 に準拠しようという気はなかったはずなので、
この規定を守るいわれはありませんが、今後 IEEE 754:2008 をサポートしよう
という環境はこの形式の出力を行うことになります。
なお、C 言語 以外だと Java は 1.5 でこの形式をサポートしているようです。

というわけで、既にメジャーな 2 言語によってサポートされ、今後もサポート
する言語は増えることが予想されるので、リテラルとは独立にサポートして
いいのではないかと思います。

--
NARUSE, Yui

=end

Actions #23

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
(2010/03/27 23:49), Tanaka Akira wrote:

2010年3月27日19:14 NARUSE, Yui:

ML 上での最大の use case は浮動小数点数を理解していないユーザへの説明用でしょうね。

その用途に必要なのは、String#to_f より、まず Float#to_s なんじゃないですかね。

printf でもいいですが。

理解していないユーザのために、通常の利便性を落とすことは考えませんでした。
なので、printf でいいんじゃないかなぁと思います。
Float#to_s(16) で期待するのがこの形式かというと、また少し悩むところがありますし。

なお、「ML 上での」とつけたのは観測可能だからでした。

個人的な利用でいうと、Math.atanh や Math.log 周りのバグを修正しているときに、
それぞれの環境の Ruby にパッチを当てつつ、%a の出力をにらめっこしていました。
10 進だと 10 進変換が入るので何が起きているかわからないし、
pack だとどこまでが指数部か一目でわからないので、この形式は有用でした。

ついでに missing/vsnprint.f も含めた printf("%a") のパッチ。

diff --git a/LEGAL b/LEGAL
index 991bb4d..c28a0b5 100644
--- a/LEGAL
+++ b/LEGAL
@@ -123,6 +123,32 @@ win32/win32.[ch]:
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the perl README file.

+util.c (partly):
+

  • Copyright (c) 2004-2008 David Schultz
  • All rights reserved.
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions
  • are met:
    1. Redistributions of source code must retain the above copyright
  •  notice, this list of conditions and the following disclaimer.
    
    1. Redistributions in binary form must reproduce the above copyright
  •  notice, this list of conditions and the following disclaimer in the
    
  •  documentation and/or other materials provided with the distribution.
    
  • THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  • ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  • IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  • ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  • FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  • DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  • OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  • HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  • LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  • OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  • SUCH DAMAGE.

random.c

This file is under the new-style BSD license.

diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
index 4e19651..acb09c9 100644
--- a/missing/vsnprintf.c
+++ b/missing/vsnprintf.c
@@ -559,7 +559,7 @@ BSD_vfprintf(FILE *fp, const char fmt0, va_list ap)
struct __suio uio; /
output information: summary /
struct __siov iov[NIOV];/
... and individual io vectors /
char buf[BUF]; /
space for %c, %[diouxX], %[eEfgG] */

  • char ox[2]; /* space for 0x hex-prefix */
  • char ox[4]; /* space for 0x hex-prefix, hexadecimal's 1. */
    char *const ebuf = buf + sizeof(buf);
    #if SIZEOF_LONG > SIZEOF_INT
    long ln;
    @@ -784,6 +784,11 @@ reswitch: switch (ch) {
    base = 10;
    goto number;
    #ifdef FLOATING_POINT
  •  case 'a':
    
  •  case 'A':
    
  •  	if (prec >= 0)
    
  •  		prec++;
    
  •  	goto fp_begin;
     case 'e':		/* anomalous precision */
     case 'E':
     	if (prec != 0)
    

@@ -822,7 +827,12 @@ fp_begin: _double = va_arg(ap, double);
else
ch = 'g';
}

  •  	if (ch <= 'e') {	/* 'e' or 'E' fmt */
    
  •  	if (ch == 'a' || ch == 'A') {
    
  •  		--expt;
    
  •  		expsize = exponent(expstr, expt, ch + 'p' - 'a');
    
  •  		size = expsize + ndig;
    
  •  	}
    
  •  	else if (ch <= 'e') {	/* 'e' or 'E' fmt */
     		--expt;
     		expsize = exponent(expstr, expt, ch);
     		size = expsize + ndig;
    

@@ -1048,7 +1058,20 @@ long_len:
if ((flags & FPT) == 0) {
PRINT(cp, fieldsz);
} else { /* glue together f_p fragments */

  •  	if (ch >= 'f') {	/* 'f' or 'g' */
    
  •  	if (ch == 'a' || ch == 'A') {
    
  •  		ox[0] = '0';
    
  •  		ox[1] = ch + ('x' - 'a');
    
  •  		PRINT(ox, 2);
    
  •  		if (ndig > 1 || flags & ALT) {
    
  •  			ox[2] = *cp++;
    
  •  			ox[3] = '.';
    
  •  			PRINT(ox+2, 2);
    
  •  			PRINT(cp, ndig-1);
    
  •  		} else	/* XpYYY */
    
  •  			PRINT(cp, 1);
    
  •  		PRINT(expstr, expsize);
    
  •  	}
    
  •  	else if (ch >= 'f') {	/* 'f' or 'g' */
     		if (_double == 0) {
     		/* kludge for __dtoa irregularity */
     			if (ndig <= 1 &&
    

@@ -1112,6 +1135,7 @@ error:
#ifdef FLOATING_POINT

extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
+extern char *BSD__hdtoa(double, const char *, int, int *, int *, char **);

static char *
cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
@@ -1135,7 +1159,14 @@ cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
} else {
*sign = '\000';
}

  • digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
  • if (ch == 'a' || ch =='A') {
  •  digits = BSD__hdtoa(value,
    
  •      ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF",
    
  •      ndigits, decpt, &dsgn, &rve);
    
  • }
  • else {
  •  digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
    
  • }
    memcpy(buf, digits, rve - digits);
    xfree(digits);
    rve = buf + (rve - digits);
    @@ -1181,7 +1212,7 @@ exponent(p0, exp, fmtch)
    for (; t < expbuf + MAXEXP; *p++ = *t++);
    }
    else {
  •  *p++ = '0';
    
  •  if (fmtch & 15) *p++ = '0'; /* other than p or P */
     *p++ = to_char(exp);
    
    }
    return (int)(p - p0);
    diff --git a/sprintf.c b/sprintf.c
    index bec0569..e26b833 100644
    --- a/sprintf.c
    +++ b/sprintf.c
    @@ -227,6 +227,10 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
    •        | equal to the precision, or in dd.dddd form otherwise.
      
    •        | The precision specifies the number of significant digits.
      
    •    G   | Equivalent to `g', but use an uppercase `E' in exponent form.
      
    •    a   | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
      
    •        | which is consisted from optional sign, "0x", fraction part
      
    •        | as hexadecimal, "p", and exponential part as decimal.
      
    •    A   | Equivalent to `a', but use uppercase `X' and `P'.
      
    •  Field |  Other Format
      
    •  ------+--------------------------------------------------------------
      

@@ -244,7 +248,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

  • Flag | Applies to | Meaning
  • ---------+---------------+-----------------------------------------
  • space | bBdiouxX | Leave a space at the start of
    •         | eEfgG         | non-negative numbers.
      
    •         | aAeEfgG       | non-negative numbers.
      
    •         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
      
    •         |               | a minus sign with absolute value for
      
    •         |               | negative values.
      

@@ -255,19 +259,19 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

  •         |               | sprintf string.
    
  • ---------+---------------+-----------------------------------------
  • #       | bBoxX         | Use an alternative format.
    
    •         | eEfgG         | For the conversions `o', increase the precision
      
    •         | aAeEfgG       | For the conversions `o', increase the precision
      
    •         |               | until the first digit will be `0' if
      
    •         |               | it is not formatted as complements.
      
    •         |               | For the conversions `x', `X', `b' and `B'
      
    •         |               | on non-zero, prefix the result with ``0x'',
      
    •         |               | ``0X'', ``0b'' and ``0B'', respectively.
      
    •         |               | For `e', `E', `f', `g', and 'G',
      
    •         |               | For `a', `A', `e', `E', `f', `g', and 'G',
      
    •         |               | force a decimal point to be added,
      
    •         |               | even if no digits follow.
      
    •         |               | For `g' and 'G', do not remove trailing zeros.
      
    • ---------+---------------+-----------------------------------------
      •    | bBdiouxX      | Add a leading plus sign to non-negative
        
    •         | eEfgG         | numbers.
      
    •         | aAeEfgG       | numbers.
      
    •         | (numeric fmt) | For `o', `x', `X', `b' and `B', use
      
    •         |               | a minus sign with absolute value for
      
    •         |               | negative values.
      

@@ -275,7 +279,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)

    •    | all           | Left-justify the result of this conversion.
      
  • ---------+---------------+-----------------------------------------
  • 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
    •         | eEfgG         | For `o', `x', `X', `b' and `B', radix-1
      
    •         | aAeEfgG       | For `o', `x', `X', `b' and `B', radix-1
      
    •         | (numeric fmt) | is used for negative numbers formatted as
      
    •         |               | complements.
      
    • ---------+---------------+-----------------------------------------
      @@ -983,6 +987,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
      case 'G':
      case 'e':
      case 'E':
  • case 'a':

  • case 'A':
    {
    VALUE val = GETARG();
    double fval;
    diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb
    index 15424d9..f8dbbd5 100644
    --- a/test/ruby/test_sprintf.rb
    +++ b/test/ruby/test_sprintf.rb
    @@ -191,6 +191,19 @@ class TestSprintf < Test::Unit::TestCase
    assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
    end

  • def test_float_hex

  • assert_equal("-0x0p+0", sprintf("%a", -0.0))

  • assert_equal("0x0p+0", sprintf("%a", 0.0))

  • assert_equal("0x1p-1", sprintf("%a", 0.5))

  • assert_equal("0x1p+0", sprintf("%a", 1.0))

  • assert_equal("0x1p+1", sprintf("%a", 2.0))

  • assert_equal("0x1.193ea7aad030ap+0", sprintf("%a", Math.log(3)))

  • assert_equal("0X1.193EA7AAD030AP+0", sprintf("%A", Math.log(3)))

  • assert_equal("0x1p+10", sprintf("%a", 1024))

  • assert_equal("0x1.23456p+789", sprintf("%a", 3.704450999893983e+237))

  • assert_equal("0x1p-1074", sprintf("%a", 4.9e-324))

  • end

  • BSIZ = 120

    def test_skip
    diff --git a/util.c b/util.c
    index 9cdb563..88914be 100644
    --- a/util.c
    +++ b/util.c
    @@ -3860,6 +3857,149 @@ ruby_each_words(const char str, void (func)(const char, int, void), void *ar
    }
    }

+/*-

    • All rights reserved.
    • Redistribution and use in source and binary forms, with or without
    • modification, are permitted provided that the following conditions
    • are met:
      1. Redistributions of source code must retain the above copyright
    • notice, this list of conditions and the following disclaimer.
      1. Redistributions in binary form must reproduce the above copyright
    • notice, this list of conditions and the following disclaimer in the
    • documentation and/or other materials provided with the distribution.
    • THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    • ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    • IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    • ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    • FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    • DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    • OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    • HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    • LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    • OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    • SUCH DAMAGE.
  • */

+#define DBL_MANH_SIZE 20
+#define DBL_MANL_SIZE 32
+#define INFSTR "Infinity"
+#define NANSTR "NaN"
+#define DBL_ADJ (DBL_MAX_EXP - 2)
+#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
+#define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1)
+#define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | (v << Exp_shift)))
+#define dmanh_get(u) ((int)(word0(u) & Frac_mask))
+#define dmanl_get(u) ((int)word1(u))
+
+
+/*

    • This procedure converts a double-precision number in IEEE format
    • into a string of hexadecimal digits and an exponent of 2. Its
    • behavior is bug-for-bug compatible with dtoa() in mode 2, with the
    • following exceptions:
      • An ndigits < 0 causes it to use as many digits as necessary to
    • represent the number exactly.
      • The additional xdigs argument should point to either the string
    • "0123456789ABCDEF" or the string "0123456789abcdef", depending on
    • which case is desired.
      • This routine does not repeat dtoa's mistake of setting decpt
    • to 9999 in the case of an infinity or NaN. INT_MAX is used
    • for this purpose instead.
    • Note that the C99 standard does not specify what the leading digit
    • should be for non-zero numbers. For instance, 0x1.3p3 is the same
    • as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes
    • the leading digit a 1. This ensures that the exponent printed is the
    • actual base-2 exponent, i.e., ilogb(d).
    • Inputs: d, xdigs, ndigits
    • Outputs: decpt, sign, rve
  • */
    +char *
    +BSD__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
  • char **rve)
    +{
  • U u;
  • char *s, *s0;
  • int bufsize;
  • uint32_t manh, manl;
  • u.d = d;
  • if (word0(u) & Sign_bit) {
  •  /* set sign for everything, including 0's and NaNs */
    
  •  *sign = 1;
    
  •  word0(u) &= ~Sign_bit;  /* clear sign bit */
    
  • }
  • else
  •  *sign = 0;
    
  • switch (fpclassify(d)) {
  • case FP_NORMAL:
  •  *decpt = dexp_get(u) - DBL_ADJ;
    
  •  break;
    
  • case FP_ZERO:
  •  *decpt = 1;
    
  •  return (nrv_alloc("0", rve, 1));
    
  • case FP_SUBNORMAL:
  •  u.d *= 5.363123171977039e+154 /* 0x1p514 */;
    
  •  *decpt = dexp_get(u) - (514 + DBL_ADJ);
    
  •  break;
    
  • case FP_INFINITE:
  •  *decpt = INT_MAX;
    
  •  return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
    
  • default: /* FP_NAN or unrecognized */
  •  *decpt = INT_MAX;
    
  •  return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
    
  • }
  • /* FP_NORMAL or FP_SUBNORMAL */
  • if (ndigits == 0) /* dtoa() compatibility */
  •  ndigits = 1;
    
  • /*
    • If ndigits < 0, we are expected to auto-size, so we allocate
    • enough space for all the digits.
  • */
  • bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
  • s0 = rv_alloc(bufsize);
  • /* Round to the desired number of digits. */
  • if (SIGFIGS > ndigits && ndigits > 0) {
  •  float redux = 1.0;
    
  •  int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
    
  •  dexp_set(u, offset);
    
  •  u.d += redux;
    
  •  u.d -= redux;
    
  •  *decpt += dexp_get(u) - offset;
    
  • }
  • manh = dmanh_get(u);
  • manl = dmanl_get(u);
  • *s0 = '1';
  • for (s = s0 + 1; s < s0 + bufsize; s++) {
  •  *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf];
    
  •  manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4));
    
  •  manl <<= 4;
    
  • }
  • /* If ndigits < 0, we are expected to auto-size the precision. */
  • if (ndigits < 0) {
  •  for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
    
  •  	;
    
  • }
  • s = s0 + ndigits;
  • *s = '\0';
  • if (rve != NULL)
  •  *rve = s;
    
  • return (s0);
    +}

#ifdef __cplusplus
#if 0
{

--
NARUSE, Yui

=end

Actions #24

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

これだけだと「直感的に気に入らない。」としか読めないのでなんとか言語化してもらえませんか。
(中略)
私から見ると成瀬さんの意見は「賛成できないけどいいたいことは分かる。」ですが
ふなばさんのメールはそもそも言いたい事がよく分からないので返信が書きにくいです。

一旦長めの返事書いたんだけど、また分らないって言われそうなんで、もう
to_f は strtod(3) ですって事でいいかな。こんなところで頑張っても俺的に
バランスを欠いてるし。

=end

Actions #25

Updated by tadf (tadayoshi funaba) about 14 years ago

=begin

統一性とバランスの問題です。

何の統一性とバランスでしょう。
String#to_i との統一性とバランス、でしょうか。

[ruby-dev:40728] で書いたようなことです。

たとえば、to_i は16進数を拒否できますが、to_f は選択肢がありません。両
者は違いが出てきています。僕は成瀬さんがいう利点についてはあまり異論は
ないですよ。失うものがあるように感じて、それが気になっているだけです。
実際、今後も to_f は殆どの場合は、10進数用としてつかわれる筈です。to_i
は16進数も扱えますが、利用者はそのことについて忘れても問題ありません。
必要な時は、to_i にオプションがあったということを思い出せます。to_f に
とって必要でなくても、to_i と to_f をつかう利用者から見れば、同じような
使い勝手で、同じようにオプションが用意されているほうが、分り易いと思い
ます。これが統一性の話。また、失うものがあるとすれば、本当に、Float()
や to_f で提供する必要性、価値があるか、バランスのとれた解説方法なのか
疑問だったのです。さしあたりは、lib/scanf.rb でもいいのではないか。この
あたりがバランスの話。

でも、まあ to_f は strtod(3) なんだろうだから、もういいと思います。これ
も理解してもらえるのかどうか分りませんがら。

=end

Actions #26

Updated by matz (Yukihiro Matsumoto) about 14 years ago

=begin
まつもと ゆきひろです

すいません、忙しくて放置してました。

In message "Re: [ruby-dev:40650] [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように"
on Tue, 16 Mar 2010 04:01:52 +0900, Yui NARUSE writes:
|
|Feature #2969: String#to_f が -h.hhh±pd を解釈できるように
|http://redmine.ruby-lang.org/issues/show/2969
|
|起票者: Yui NARUSE
|ステータス: Open, 優先度: Normal
|
|C99 の printf には a という指定子があります。
|
| aA The argument is printed in style ‘[-h.hhh±pd]’ where there is
| one digit before the hexadecimal point and the number after
| is equal to the precision specification for the argument;
| when the precision is missing, enough digits are produced to
| convey the argument's exact double-precision floating-point
| representation. The values ∞ and NaN are printed as ‘inf’
| and ‘nan’, respectively.

|で、この形式を使っているのですが、RubyのString#to_f で解釈してくれず悲しくなるので、
|解釈できるようにしませんか。

最終決定ではありませんが、私の判断は以下の通りです。

  • 1.9.2には導入しない。将来とも拒否というわけではない。

まず、この機能ですが、必要性はさほど高くないので、導入するの
であれば printf と同時に導入すべきだと思います。でも、実装が
間に合わないので printf は提案しないということでしたら、無理
に 1.9.2 に導入せずに、printfの実装も対にするべきだと思いま
す。

さて、時期の問題はともかくとして、最終的な仕様がどうあるべき
かについてですが、Rubyには「浮動小数点表現の解釈」を行う機能
は複数あります。

(a) 浮動小数点リテラル
(b) Float#to_f
(c) Float()
(d) lib/scanf.rb

で、今回導入検討している表現はメソッド呼び出しとコンフリクト
する可能性があるので (a) は対象にしないというのがコンセンサ
スだと思います。私も賛成します。

次に (b) と (c) ですが、現在の Float() と to_f には、

  • Float()は表現に厳しく、間違った表現は積極的に例外にする
  • to_f は適当に解釈し、間違った表現には0.0を返す

という違いがあります。さらに Integer() と to_i との類推からは、
「0x」などの解釈はFloatが行い、to_fは行わないということを期待
してもよいのではないかと思います。

とすると、将来 %a 表現の解釈を導入する際にはFloat()がこの形式
を解釈し、to_fは行わないというのが、自然ではないのかと思いま
す。もっとも、これは私の意見と言うだけで、最終決定ではありま
せんが。

最後に (d) scanf ですが、printfが %a を採用したあかつきには、
scanf も %a を導入した方がよいと思います。

to_iやto_fがエラーに対して 0 を返すのは、後悔している仕様の
一つですが、今さら変えられないですね。

                             まつもと ゆきひろ /:|)

p.s.
それはそれとして、"4._9".to_f が 4.9 なのは、うーん。

=end

Actions #27

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

(2010/03/29 7:04), Yukihiro Matsumoto wrote:

まつもと ゆきひろです

すいません、忙しくて放置してました。

In message "Re: [ruby-dev:40650] [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように"
on Tue, 16 Mar 2010 04:01:52 +0900, Yui NARUSE writes:
|
|Feature #2969: String#to_f が -h.hhh±pd を解釈できるように
|http://redmine.ruby-lang.org/issues/show/2969
|
|起票者: Yui NARUSE
|ステータス: Open, 優先度: Normal
|
|C99 の printf には a という指定子があります。
|
| aA The argument is printed in style ‘[-h.hhh±pd]’ where there is
| one digit before the hexadecimal point and the number after
| is equal to the precision specification for the argument;
| when the precision is missing, enough digits are produced to
| convey the argument's exact double-precision floating-point
| representation. The values ∞ and NaN are printed as ‘inf’
| and ‘nan’, respectively.

|で、この形式を使っているのですが、RubyのString#to_f で解釈してくれず悲しくなるので、
|解釈できるようにしませんか。

最終決定ではありませんが、私の判断は以下の通りです。

  • 1.9.2には導入しない。将来とも拒否というわけではない。

まず、この機能ですが、必要性はさほど高くないので、導入するの
であれば printf と同時に導入すべきだと思います。でも、実装が
間に合わないので printf は提案しないということでしたら、無理
に 1.9.2 に導入せずに、printfの実装も対にするべきだと思いま
す。

missing を含めた printf の実装は、[ruby-dev:40801] にあります。
ので、この点に関して時期的な問題はないかと思います。

さて、時期の問題はともかくとして、最終的な仕様がどうあるべき
かについてですが、Rubyには「浮動小数点表現の解釈」を行う機能
は複数あります。

(a) 浮動小数点リテラル
(b) Float#to_f
(c) Float()
(d) lib/scanf.rb

で、今回導入検討している表現はメソッド呼び出しとコンフリクト
する可能性があるので (a) は対象にしないというのがコンセンサ
スだと思います。私も賛成します。

次に (b) と (c) ですが、現在の Float() と to_f には、

  • Float()は表現に厳しく、間違った表現は積極的に例外にする
  • to_f は適当に解釈し、間違った表現には0.0を返す

という違いがあります。さらに Integer() と to_i との類推からは、
「0x」などの解釈はFloatが行い、to_fは行わないということを期待
してもよいのではないかと思います。

とすると、将来 %a 表現の解釈を導入する際にはFloat()がこの形式
を解釈し、to_fは行わないというのが、自然ではないのかと思いま
す。もっとも、これは私の意見と言うだけで、最終決定ではありま
せんが。

なるほど、わたしは手軽に使えればよいので異論はありません。

最後に (d) scanf ですが、printfが %a を採用したあかつきには、
scanf も %a を導入した方がよいと思います。

scanf の実装は [ruby-dev:40799] に示しています。

to_iやto_fがエラーに対して 0 を返すのは、後悔している仕様の
一つですが、今さら変えられないですね。

次のチャンスは 2.0 ですかねぇ。

--
NARUSE, Yui

=end

Actions #28

Updated by matz (Yukihiro Matsumoto) about 14 years ago

=begin
まつもと ゆきひろです

In message "Re: [ruby-dev:40816] Re: [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように"
on Mon, 29 Mar 2010 08:08:37 +0900, "NARUSE, Yui" writes:

|> * 1.9.2には導入しない。将来とも拒否というわけではない。
|>
|> まず、この機能ですが、必要性はさほど高くないので、導入するの
|> であれば printf と同時に導入すべきだと思います。でも、実装が
|> 間に合わないので printf は提案しないということでしたら、無理
|> に 1.9.2 に導入せずに、printfの実装も対にするべきだと思いま
|> す。
|
|missing を含めた printf の実装は、[ruby-dev:40801] にあります。
|ので、この点に関して時期的な問題はないかと思います。

おお、それは見落としてました。でも、成瀬さんは「printfは1.9.3
まで待つ」とおっしゃっていたように思います。時期的な問題はな
いとすると、それはなぜ?

|> 最後に (d) scanf ですが、printfが %a を採用したあかつきには、
|> scanf も %a を導入した方がよいと思います。
|
|scanf の実装は [ruby-dev:40799] に示しています。

これについても時期的な問題はないわけですね。

|> to_iやto_fがエラーに対して 0 を返すのは、後悔している仕様の
|> 一つですが、今さら変えられないですね。
|
|次のチャンスは 2.0 ですかねぇ。

いやぁ、後悔しているからといって互換性問題を安易に導入しちゃ
うと、移行の妨げになっちゃいますからねえ。

                             まつもと ゆきひろ /:|)

=end

Actions #29

Updated by naruse (Yui NARUSE) about 14 years ago

=begin
成瀬です。

2010年3月29日9:08 Yukihiro Matsumoto :

まつもと ゆきひろです

In message "Re: [ruby-dev:40816] Re: [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように"
on Mon, 29 Mar 2010 08:08:37 +0900, "NARUSE, Yui" writes:

|> * 1.9.2には導入しない。将来とも拒否というわけではない。
|>
|> まず、この機能ですが、必要性はさほど高くないので、導入するの
|> であれば printf と同時に導入すべきだと思います。でも、実装が
|> 間に合わないので printf は提案しないということでしたら、無理
|> に 1.9.2 に導入せずに、printfの実装も対にするべきだと思いま
|> す。
|
|missing を含めた printf の実装は、[ruby-dev:40801] にあります。
|ので、この点に関して時期的な問題はないかと思います。

おお、それは見落としてました。でも、成瀬さんは「printfは1.9.3
まで待つ」とおっしゃっていたように思います。時期的な問題はな
いとすると、それはなぜ?

あぁ、そこを受けていたのですね、当時はもっと実装に時間がかかると思ったからです。
実際に必要だったのは関数一つの調整だったので、
土日で終わり [ruby-dev:40801] での投稿につながるわけです。

|> 最後に (d) scanf ですが、printfが %a を採用したあかつきには、
|> scanf も %a を導入した方がよいと思います。
|
|scanf の実装は [ruby-dev:40799] に示しています。

これについても時期的な問題はないわけですね。

はい。

|> to_iやto_fがエラーに対して 0 を返すのは、後悔している仕様の
|> 一つですが、今さら変えられないですね。
|
|次のチャンスは 2.0 ですかねぇ。

いやぁ、後悔しているからといって互換性問題を安易に導入しちゃ
うと、移行の妨げになっちゃいますからねえ。

以前 [ruby-dev:39851] で to_hoge 周りの整理を仰っていましたが、
その辺が 2.0 では議論が落ち着くだろう (いや、落ち着いて欲しい) と
思っていまして、その場合はそのドサクサに紛れて変えられるかなーと。
to_f はそのままで、新明示的変換指示メソッドだけ変えるでもいいのでしょうが。

--
NARUSE, Yui

=end

Actions #30

Updated by matz (Yukihiro Matsumoto) about 14 years ago

=begin
まつもと ゆきひろです

In message "Re: [ruby-dev:40820] Re: [Feature #2969] String#to_f が -h.hhh±pd を解釈できるように"
on Mon, 29 Mar 2010 09:33:27 +0900, "NARUSE, Yui" writes:

|> おお、それは見落としてました。でも、成瀬さんは「printfは1.9.3
|> まで待つ」とおっしゃっていたように思います。時期的な問題はな
|> いとすると、それはなぜ?
|
|あぁ、そこを受けていたのですね、当時はもっと実装に時間がかかると思ったからです。
|実際に必要だったのは関数一つの調整だったので、
|土日で終わり [ruby-dev:40801] での投稿につながるわけです。

時系列を見失っていたようです。実装があるとすると、残るは

  • 私が提示した仕様で問題ないか
  • それは 1.9.2 に含めるかどうか

ですね。前者は実際に利用することを考えておられる方が判断して
ください。後者は Yuguiさんの issue ですね。

|以前 [ruby-dev:39851] で to_hoge 周りの整理を仰っていましたが、
|その辺が 2.0 では議論が落ち着くだろう (いや、落ち着いて欲しい) と
|思っていまして、その場合はそのドサクサに紛れて変えられるかなーと。
|to_f はそのままで、新明示的変換指示メソッドだけ変えるでもいいのでしょうが。

そううまくいくかなあ。考えさせてください。

                             まつもと ゆきひろ /:|)

=end

Actions #31

Updated by yugui (Yuki Sonoda) about 14 years ago

=begin
String#to_fやリテラルにはちょっと躊躇しますが、今回はそれは入らないと言うことですのでおおむね差し支えないと思います。

影響範囲を読み切れない部分があるのですが、リリースまでに寄せられた苦情次第ではrevertもあり得るという条件付きで1.9.2へ取り込みたいと思います。
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0