Feature #2968

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

Added by Yui NARUSE about 4 years ago. Updated over 1 year ago.

[ruby-dev:40649]
Status:Assigned
Priority:Normal
Assignee:Kenta Murata
Category:core
Target version:next minor

Description

=begin
数値の正負を返すメソッドが欲しいです。
主たる想定用途は 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) に習う)
あたりでしょうか。

いかがでしょう。
=end


Related issues

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

History

#1 Updated by Kenta Murata about 4 years ago

=begin
村田です。

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/

=end

#2 Updated by Shyouhei Urabe about 4 years ago

  • Status changed from Open to Rejected

=begin
f > 0 or 1.0 / f > 0

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

#3 Updated by Yui NARUSE about 4 years ago

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

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

#4 Updated by Kenta Murata about 4 years ago

=begin
むらたです。

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/

=end

#5 Updated by Yui NARUSE about 4 years ago

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

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

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

#6 Updated by Shyouhei Urabe about 4 years ago

=begin
Yui NARUSE さんは書きました:

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

そうです。

で、そもそもの動機は doubleを生成するメソッドのテストをする際に、
d = -0.0
assertequal(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
=end

#7 Updated by Yui NARUSE about 4 years ago

=begin

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

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

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

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

#8 Updated by Yui NARUSE about 4 years ago

=begin
成瀬です。

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

=end

#9 Updated by Yui NARUSE about 4 years ago

=begin
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

=end

#10 Updated by Yui NARUSE about 4 years ago

=begin
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

=end

#11 Updated by Akinori MUSHA over 3 years ago

  • Status changed from Rejected to Assigned
  • Assignee set to Kenta Murata

=begin
フィードバックがあるのにRejectedのままなので再開します。

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

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

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

#12 Updated by Kenta Murata over 2 years ago

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

分かってないのは Complex#sign の挙動です。どう動けば良いんですかね?

#13 Updated by Hiro Asari about 2 years ago

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

#14 Updated by Yutaka HARA over 1 year ago

  • Target version set to next minor

Also available in: Atom PDF