End of Life Ruby 3.1 has reached end of life and gets no more fixes. Switch to Ruby 4.0 →
BigDecimal.mode
static VALUE
BigDecimal_mode(int argc, VALUE *argv, VALUE self)
{
VALUE which;
VALUE val;
unsigned long f,fo;
rb_scan_args(argc, argv, "11", &which, &val);
f = (unsigned long)NUM2INT(which);
if (f & VP_EXCEPTION_ALL) {
/* Exception mode setting */
fo = VpGetException();
if (val == Qnil) return INT2FIX(fo);
if (val != Qfalse && val!=Qtrue) {
rb_raise(rb_eArgError, "second argument must be true or false");
return Qnil; /* Not reached */
}
if (f & VP_EXCEPTION_INFINITY) {
VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
(fo & (~VP_EXCEPTION_INFINITY))));
}
fo = VpGetException();
if (f & VP_EXCEPTION_NaN) {
VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
(fo & (~VP_EXCEPTION_NaN))));
}
fo = VpGetException();
if (f & VP_EXCEPTION_UNDERFLOW) {
VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
(fo & (~VP_EXCEPTION_UNDERFLOW))));
}
fo = VpGetException();
if(f & VP_EXCEPTION_ZERODIVIDE) {
VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
(fo & (~VP_EXCEPTION_ZERODIVIDE))));
}
fo = VpGetException();
return INT2FIX(fo);
}
if (VP_ROUND_MODE == f) {
/* Rounding mode setting */
unsigned short sw;
fo = VpGetRoundMode();
if (NIL_P(val)) return INT2FIX(fo);
sw = check_rounding_mode(val);
fo = VpSetRoundMode(sw);
return INT2FIX(fo);
}
rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
return Qnil;
}
Returns an integer representing the mode settings for exception handling and rounding.
These modes control exception handling:
-
BigDecimal::EXCEPTION_NaN.
-
BigDecimal::EXCEPTION_INFINITY.
-
BigDecimal::EXCEPTION_UNDERFLOW.
-
BigDecimal::EXCEPTION_OVERFLOW.
-
BigDecimal::EXCEPTION_ZERODIVIDE.
-
BigDecimal::EXCEPTION_ALL.
Values for setting for exception handling:
-
true: sets the givenmodetotrue. -
false: sets the givenmodetofalse. -
nil: does not modify the mode settings.
You can use method BigDecimal.save_exception_mode to temporarily change, and then automatically restore, exception modes.
For clarity, some examples below begin by setting all exception modes to false.
This mode controls the way rounding is to be performed:
-
BigDecimal::ROUND_MODE
You can use method BigDecimal.save_rounding_mode to temporarily change, and then automatically restore, the rounding mode.
NaNs
Mode BigDecimal::EXCEPTION_NaN controls behavior when a BigDecimal NaN is created.
Settings:
-
false(default): ReturnsBigDecimal('NaN'). -
true: RaisesFloatDomainError.
Examples:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 BigDecimal('NaN') # => NaN BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2 BigDecimal('NaN') # Raises FloatDomainError
Infinities
Mode BigDecimal::EXCEPTION_INFINITY controls behavior when a BigDecimal Infinity or -Infinity is created. Settings:
-
false(default): ReturnsBigDecimal('Infinity')orBigDecimal('-Infinity'). -
true: RaisesFloatDomainError.
Examples:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 BigDecimal('Infinity') # => Infinity BigDecimal('-Infinity') # => -Infinity BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1 BigDecimal('Infinity') # Raises FloatDomainError BigDecimal('-Infinity') # Raises FloatDomainError
Underflow
Mode BigDecimal::EXCEPTION_UNDERFLOW controls behavior when a BigDecimal underflow occurs. Settings:
-
false(default): ReturnsBigDecimal('0')orBigDecimal('-Infinity'). -
true: RaisesFloatDomainError.
Examples:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 def flow_under x = BigDecimal('0.1') 100.times { x *= x } end flow_under # => 100 BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4 flow_under # Raises FloatDomainError
Overflow
Mode BigDecimal::EXCEPTION_OVERFLOW controls behavior when a BigDecimal overflow occurs. Settings:
-
false(default): ReturnsBigDecimal('Infinity')orBigDecimal('-Infinity'). -
true: RaisesFloatDomainError.
Examples:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 def flow_over x = BigDecimal('10') 100.times { x *= x } end flow_over # => 100 BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1 flow_over # Raises FloatDomainError
Zero Division
Mode BigDecimal::EXCEPTION_ZERODIVIDE controls behavior when a zero-division occurs. Settings:
-
false(default): ReturnsBigDecimal('Infinity')orBigDecimal('-Infinity'). -
true: RaisesFloatDomainError.
Examples:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 one = BigDecimal('1') zero = BigDecimal('0') one / zero # => Infinity BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16 one / zero # Raises FloatDomainError
All Exceptions
Mode BigDecimal::EXCEPTION_ALL controls all of the above:
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23
Rounding
Mode BigDecimal::ROUND_MODE controls the way rounding is to be performed; its setting values are:
-
ROUND_UP: Round away from zero. Aliased as:up. -
ROUND_DOWN: Round toward zero. Aliased as:downand:truncate. -
ROUND_HALF_UP: Round toward the nearest neighbor; if the neighbors are equidistant, round away from zero. Aliased as:half_upand:default. -
ROUND_HALF_DOWN: Round toward the nearest neighbor; if the neighbors are equidistant, round toward zero. Aliased as:half_down. -
ROUND_HALF_EVEN(Banker’s rounding): Round toward the nearest neighbor; if the neighbors are equidistant, round toward the even neighbor. Aliased as:half_evenand:banker. -
ROUND_CEILING: Round toward positive infinity. Aliased as:ceilingand:ceil. -
ROUND_FLOOR: Round toward negative infinity. Aliased as:floor:.