* numeric.c (int_truncate): add an optional parameter, digits, as
  well as Integer#round.  [Feature #12245]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54624 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2016-04-18 03:55:33 +00:00
Родитель adc7cb240a
Коммит 39f31b8c87
4 изменённых файлов: 95 добавлений и 4 удалений

Просмотреть файл

@ -1,3 +1,8 @@
Mon Apr 18 12:55:31 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* numeric.c (int_truncate): add an optional parameter, digits, as
well as Integer#round. [Feature #12245]
Sun Apr 17 04:18:56 2016 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org>
* tool/redmine-backporter.rb: revisions are strings.

4
NEWS
Просмотреть файл

@ -43,8 +43,8 @@ with all sufficient information, see the ChangeLog file or Redmine
* Integer
* Integer#ceil and Integer#floor now take an optional digits, as well
as Integer#round. [Feature #12245]
* Integer#ceil, Integer#floor, and Integer#truncate now take an optional
digits, as well as Integer#round. [Feature #12245]
* String

Просмотреть файл

@ -1935,6 +1935,36 @@ rb_int_ceil(VALUE num, int ndigits)
return rb_int_plus(num, rb_int_minus(f, rb_int_modulo(num, f)));
}
VALUE
rb_int_truncate(VALUE num, int ndigits)
{
VALUE f;
VALUE m;
if (int_round_zero_p(num, ndigits))
return INT2FIX(0);
f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
int neg = x < 0;
if (neg) x = -x;
x = x / y * y;
if (neg) x = -x;
return LONG2NUM(x);
}
if (RB_TYPE_P(f, T_FLOAT)) {
/* then int_pow overflow */
return INT2FIX(0);
}
m = rb_int_modulo(num, f);
if (int_neg_p(num)) {
return rb_int_plus(num, rb_int_minus(f, m));
}
else {
return rb_int_minus(num, m);
}
}
/*
* call-seq:
* float.round([ndigits]) -> integer or float
@ -2817,7 +2847,7 @@ rb_num2ull(VALUE val)
*
* As +int+ is already an Integer, all these methods simply return the receiver.
*
* Synonyms are #to_int, #truncate.
* Synonyms is #to_int
*/
static VALUE
@ -4346,6 +4376,37 @@ int_ceil(int argc, VALUE* argv, VALUE num)
return rb_int_ceil(num, ndigits);
}
/*
* call-seq:
* int.truncate([ndigits]) -> integer or float
*
* Returns the smallest number than or equal to +int+ in decimal
* digits (default 0 digits).
*
* Precision may be negative. Returns a floating point number when +ndigits+
* is positive, +self+ for zero, and truncate up for negative.
*
* 1.truncate #=> 1
* 1.truncate(2) #=> 1.0
* 15.truncate(-1) #=> 10
*/
static VALUE
int_truncate(int argc, VALUE* argv, VALUE num)
{
int ndigits;
if (!rb_check_arity(argc, 0, 1)) return num;
ndigits = NUM2INT(argv[0]);
if (ndigits > 0) {
return rb_Float(num);
}
if (ndigits == 0) {
return num;
}
return rb_int_truncate(num, ndigits);
}
/*
* Document-class: ZeroDivisionError
*
@ -4518,7 +4579,7 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "to_f", int_to_f, 0);
rb_define_method(rb_cInteger, "floor", int_floor, -1);
rb_define_method(rb_cInteger, "ceil", int_ceil, -1);
rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
rb_define_method(rb_cInteger, "truncate", int_truncate, -1);
rb_define_method(rb_cInteger, "round", int_round, -1);
rb_define_method(rb_cInteger, "<=>", int_cmp, 1);

Просмотреть файл

@ -249,6 +249,31 @@ class TestInteger < Test::Unit::TestCase
assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).ceil(-1))
end
def test_truncate
assert_int_equal(11111, 11111.truncate)
assert_int_equal(11111, 11111.truncate(0))
assert_float_equal(11111.0, 11111.truncate(1))
assert_float_equal(11111.0, 11111.truncate(2))
assert_int_equal(11110, 11110.truncate(-1))
assert_int_equal(11110, 11119.truncate(-1))
assert_int_equal(11100, 11100.truncate(-2))
assert_int_equal(11100, 11199.truncate(-2))
assert_int_equal(0, 11111.truncate(-5))
assert_int_equal(+200, +299.truncate(-2))
assert_int_equal(+300, +300.truncate(-2))
assert_int_equal(-200, -299.truncate(-2))
assert_int_equal(-300, -300.truncate(-2))
assert_int_equal(+20 * 10**70, (+25 * 10**70).truncate(-71))
assert_int_equal(-20 * 10**70, (-25 * 10**70).truncate(-71))
assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).truncate(-71))
assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).truncate(-71))
assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1110, 1111_1111_1111_1111_1111_1111_1111_1111.truncate(-1))
assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).truncate(-1))
end
def test_bitwise_and_with_integer_mimic_object
def (obj = Object.new).to_int
10