Feature #2968

数値の正負を返すメソッド

Added by naruse (Yui NARUSE) about 2 years ago. Updated about 1 month ago.

[ruby-dev:40649]
Status:Assigned Start date:03/16/2010
Priority:Normal Due date:
Assignee:mrkn (Kenta Murata) % Done:

0%

Category:core
Target version:-

Description

数値の正負を返すメソッドが欲しいです。
主たる想定用途は 0.0 と -0.0 を区別したいときです。
これは、0.0 > -0.0 や 0.0 == -0.0 では知ることができません。
とりあえず flo.to_s[0] == ?- で知ることができますが、これではあんまりです。

悩みどころはいつもの通りメソッド名ですが、
* Numeric#positive? と Numeric#negative?
* Numeric#sign -> 負で -1、正で 1
* Numeric#sign? -> 負で true, 正で false (signbit(3) に習う)
あたりでしょうか。

いかがでしょう。

Related issues

duplicated by ruby-trunk - Feature #5523: Numeric#sign の追加 Closed 10/31/2011

History

Updated by mrkn (Kenta Murata) about 2 years ago

村田です。

On 2010/03/16, at 3:38, Yui NARUSE wrote:

> 数値の正負を返すメソッドが欲しいです。
> 主たる想定用途は 0.0 と -0.0 を区別したいときです。
> これは、0.0 > -0.0 や 0.0 == -0.0 では知ることができません。
> とりあえず flo.to_s[0] == ?- で知ることができますが、これではあんまりです。
> 
> 悩みどころはいつもの通りメソッド名ですが、
> * Numeric#positive? と Numeric#negative?
> * Numeric#sign -> 負で -1、正で 1
> * Numeric#sign? -> 負で true, 正で false (signbit(3) に習う)
> あたりでしょうか。

Numeric#sign? よりは、Numeric#positive? と Numeric#negative? を提供する
方が私は好きです。

Numeric#sign も同時に提供されていて良いと思います。

ところで、これらのメソッドは Complex ではどのように振舞うんでしょう?
* Numeric で提供するメソッドは実部についての符号を扱い、
  虚部については Complex で同類のメソッドを提供する。
* Numeric で提供するメソッドを Complex からは undef する。
  実部や虚部の符号が知りたい場合は Complex#real.positive? のようにする。
この2パターンが思いつきました。

--
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: mrkn@mrkn.jp
twitter: http://twitter.com/mrkn/
blog: http://d.hatena.ne.jp/mrkn/

Updated by shyouhei (Shyouhei Urabe) about 2 years ago

  • Status changed from Open to Rejected
f > 0 or 1.0 / f > 0

ではなんでだめなんですか?

Updated by naruse (Yui NARUSE) about 2 years ago

実数のみの想定でしたので、Numericではなく、Integer, Float, Rational 個別に定義した方が良かったかもしれません。

> f > 0 or 1.0 / f > 0 ではなんでだめなんですか?
workaround としてはそちらの方がよいですね、ありがとうございます。
しかし、この方法でもまだ、1ビット読めばいいものを無駄に複雑にやっていませんか。

Updated by mrkn (Kenta Murata) about 2 years ago

むらたです。

On 2010/03/16, at 8:04, Shyouhei Urabe wrote:

> f > 0 or 1.0 / f > 0
> 
> ではなんでだめなんですか?

前者では -0.0 の符号を調べられません。
かといって後者よりは negative? と書かれている方が
分かりやすい気がします。

もう一点気になることは、1.0 / -0.0 で -Infinity が得られる事が
アーキテクチャに依存せず決まっているのかどうかです。

--
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: mrkn@mrkn.jp
twitter: http://twitter.com/mrkn/
blog: http://d.hatena.ne.jp/mrkn/

Updated by naruse (Yui NARUSE) about 2 years ago

(f > 0 or 1.0 / f > 0) という趣旨かと思います。

で、そもそもの動機は doubleを生成するメソッドのテストをする際に、
  d = -0.0
  assert_equal(0, d)
  assert_equal(-INFINITY, 1.0/d)
などと書くのは冗長というのがありました。

1.0/-0.0 は VAX だとどうなんでしょうね。

Updated by shyouhei (Shyouhei Urabe) about 2 years ago

Yui NARUSE さんは書きました:
> (f > 0 or 1.0 / f > 0) という趣旨かと思います。

そうです。

> で、そもそもの動機は doubleを生成するメソッドのテストをする際に、
>   d = -0.0
>   assert_equal(0, d)
>   assert_equal(-INFINITY, 1.0/d)
> などと書くのは冗長というのがありました。

それはsignが欲しいんじゃなくて==よりもstrictな等値判定が欲しいという話では

> 1.0/-0.0 は VAX だとどうなんでしょうね。

持ってないので存じ上げませんがべつに1.0/-0.0が-Infを生成する必要はなくて、-0.0
より小さい何かを生成すればよいので。


Attachment: signature.asc

Updated by naruse (Yui NARUSE) about 2 years ago

> > で、そもそもの動機は doubleを生成するメソッドのテストをする際に、
> >   d = -0.0
> >   assert_equal(0, d)
> >   assert_equal(-INFINITY, 1.0/d)
> > などと書くのは冗長というのがありました。
>
> それはsignが欲しいんじゃなくて==よりもstrictな等値判定が欲しいという話では

この例に関してはそうですね。
Float#eql? は 0.0 と -0.0 を区別する、とかでも。

別に正負判定は欲しくなることがたまにあるのですが、たいていは n >= 0 でよいので主張として弱くはなります。
NaN の符号もバイナリを見ないと判定できないけど、使わないしなぁ

Updated by naruse (Yui NARUSE) about 2 years ago

成瀬です。

2010年3月16日11:37 KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>:
>> チケット #2968 が更新されました。 (by Yui NARUSE)
>>
>>
>> 実数のみの想定でしたので、Numericではなく、Integer, Float, Rational 個別に定義した方が良かったかもしれません。
>>
>> > f > 0 or 1.0 / f > 0 ではなんでだめなんですか?
>> workaround としてはそちらの方がよいですね、ありがとうございます。
>> しかし、この方法でもまだ、1ビット読めばいいものを無駄に複雑にやっていませんか。
>
> 想定用途が組込みクラスのテストケースだとすると、うれしい人はとても
> 少なそうです。
> 多少冗長な書き方になっていてもかまわないのでは?

用途としてはとりあえずテストケースなのですが、背景としては Float の浮動小数点数としての
内部構造が隠蔽されすぎているという点を問題視しています。
符号だけでなく、Floatの仮数部や指数部もとれないとか。

-- 
NARUSE, Yui
naruse@airemix.jp

Updated by naruse (Yui NARUSE) about 2 years ago

2010年3月16日13:27 KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>:
>> 成瀬です。
>>
>> 2010年3月16日11:37 KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>:
>> >> チケット #2968 が更新されました。 (by Yui NARUSE)
>> >>
>> >>
>> >> 実数のみの想定でしたので、Numericではなく、Integer, Float, Rational 個別に定義した方が良かったかもしれません。
>> >>
>> >> > f > 0 or 1.0 / f > 0 ではなんでだめなんですか?
>> >> workaround としてはそちらの方がよいですね、ありがとうございます。
>> >> しかし、この方法でもまだ、1ビット読めばいいものを無駄に複雑にやっていませんか。
>> >
>> > 想定用途が組込みクラスのテストケースだとすると、うれしい人はとても
>> > 少なそうです。
>> > 多少冗長な書き方になっていてもかまわないのでは?
>>
>> 用途としてはとりあえずテストケースなのですが、背景としては Float の浮動小数点数としての
>> 内部構造が隠蔽されすぎているという点を問題視しています。
>> 符号だけでなく、Floatの仮数部や指数部もとれないとか。
>
> Cでもとれないですよね > 仮数部、指数部
> で、それで困るという話もあまり聞きません。

frexp(3) でとれますね。

> FortranやCで数値計算するときも、if (val < 目標精度) みたいな書き方で
> なんとかなっているという認識。
>
> なので、その背景のさらにバックグラウンドがあると思うのですが、
> ちょっと思い浮かびませんでした。

%a 絡みの処理を書いていて、バイナリとしてはすぐそこにあるはずのものが、
Ruby レイヤだとかなり手間をかけないと取れない理不尽さ、かな。
わたしが知らないだけなのかもしれませんが、現状指数部・仮数部を取るのって、
結構大変ですよね。

-- 
NARUSE, Yui
naruse@airemix.jp

Updated by naruse (Yui NARUSE) about 2 years ago

2010年3月16日15:16 KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>:
>> > > FortranやCで数値計算するときも、if (val < 目標精度) みたいな書き方で
>> > > なんとかなっているという認識。
>> > >
>> > > なので、その背景のさらにバックグラウンドがあると思うのですが、
>> > > ちょっと思い浮かびませんでした。
>> >
>> > %a 絡みの処理を書いていて、バイナリとしてはすぐそこにあるはずのものが、
>> > Ruby レイヤだとかなり手間をかけないと取れない理不尽さ、かな。
>> > わたしが知らないだけなのかもしれませんが、現状指数部・仮数部を取るのって、
>> > 結構大変ですよね。
>>
>> いや、大変なのは確かだと思います。
>> なので、ユースケースさえあればまったく反対しません
>>
>> IEEE754前提の定義・実装でも誰も困らないと思うので、あまり揉めないと思うし
>
> さらに後から気がつきましたが、Rubyにも Math.frexp() がすでにありますよね。
> これで不足な理由はなんでしたっけ?

おおう、それに気づきませんでした。
それでよいと思います。

それじゃ Math.signbit() があればいいな

-- 
NARUSE, Yui
naruse@airemix.jp

Updated by knu (Akinori MUSHA) over 1 year ago

  • Status changed from Rejected to Assigned
  • Assignee set to mrkn (Kenta Murata)
フィードバックがあるのにRejectedのままなので再開します。

・positive? は >0 でも良いので不要
・Math.signbit?(num) だと新しい数クラスに対応できない

というところから、 Numeric#negative? を導入するのはでどうでしょうか。
(Numericでの定義はnilで、符号が定義される各派生クラスでオーバーライドしてtrue/falseを返す)

Numeric#sign も、あれば同符号判定が楽になるかもしれません。

Updated by mrkn (Kenta Murata) 7 months ago

#5523 でも Numeric#sign が提案されてますね。 positive? や negative? は複素数に対応できないという #5513 でのまつもとさんの意見は確かに尤もだと思いました。 分かってないのは Complex#sign の挙動です。どう動けば良いんですかね?

Updated by hasari (Hiro Asari) about 1 month ago

#5523 でも触れましたが Complex#sign は z/|z| を返すのが数学的に一番よろしいかと思います。ふなばさんは #5523 では「複素数はエラーを考えています。」と仰っています。

Also available in: Atom PDF