From: NISHIMATSU Takeshi Date: 2009-02-08T21:02:32+09:00 Subject: [ruby-list:45861] numeric.c に Float#copysign を書き加えてみました 西松と申します。 練習がてらnumeric.cにFloat#copysignを書き加えてみました。 こんなことができます: $ ./miniruby -e 'p 32.1.copysign(1.0)' 32.1 $ ./miniruby -e 'p 32.1.copysign(0.0)' 32.1 $ ./miniruby -e 'p 32.1.copysign(-0.0)' -32.1 $ ./miniruby -e 'p 32.1.copysign('-0.0')' -32.1 $ ./miniruby -e 'p 32.1.copysign('123')' 32.1 $ ./miniruby -e 'p 32.1.copysign('-123')' -32.1 $ ./miniruby -e 'p 32.1.copysign(-123)' -32.1 $ ./miniruby -e 'p -32.1.copysign(0.0)' 32.1 $ ./miniruby -e 'p -32.1.copysign(Rational(1,2))'' ; echo $? 1 $ 質問なのですが、Rationalのようなto_fが定義されているものが引数に 来たときにも動くようにするには、下のexit(1);にしているところを どのように書けばよいのでしょうか。 あと、numeric.cのコメントに1つtypo(+→-)を見つけました。 $ svn diff Index: numeric.c =================================================================== --- numeric.c (revision 22120) +++ numeric.c (working copy) @@ -595,7 +595,7 @@ /* * call-seq: - * float + other => float + * float - other => float * * Returns a new float which is the difference of float * and other. @@ -1141,6 +1141,44 @@ /* * call-seq: + * x.copysign(y) => float + * + * Returns a value whose absolute value matches that of x, but whose sign matches that of y. + * + * ( 34.56).copysign(-0.0) #=> -34.56 + * (-34.56).copysign( 1.0) #=> 34.56 + * (-34.56).copysign( 1 ) #=> 34.56 + * (-34.56).copysign( 1111111111111111111111111111111111111111111111111111111111111111111111111) + * #=> 34.56 + * + */ + +static VALUE +flo_copysign(VALUE x, VALUE y) +{ + double yd, val; + switch (TYPE(y)) { + case T_FIXNUM: + yd = (double)FIX2LONG(y); + break; + case T_BIGNUM: + yd = rb_big2dbl(y); + break; + case T_FLOAT: + yd = RFLOAT_VALUE(y); + break; + case T_STRING: + yd = rb_str_to_dbl(y, Qfalse); + break; + default: + exit(1); /* rb_funcall(y, 'to_f', 0, 0)??? */ + } + val = copysign(RFLOAT_VALUE(x),yd); + return DBL2NUM(val); +} + +/* + * call-seq: * flt.zero? -> true or false * * Returns true if flt is 0.0. @@ -3262,6 +3300,7 @@ rb_define_method(rb_cFloat, "hash", flo_hash, 0); rb_define_method(rb_cFloat, "to_f", flo_to_f, 0); rb_define_method(rb_cFloat, "abs", flo_abs, 0); + rb_define_method(rb_cFloat, "copysign", flo_copysign, 1); rb_define_method(rb_cFloat, "magnitude", flo_abs, 0); rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);