Method: BigDecimal.mode

Defined in:
bigdecimal.c

.mode(mode, setting = nil) ⇒ Integer

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 given mode to true.

  • false: sets the given mode to false.

  • 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): Returns BigDecimal('NaN').

  • true: Raises FloatDomainError.

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): Returns BigDecimal('Infinity') or BigDecimal('-Infinity').

  • true: Raises FloatDomainError.

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): Returns BigDecimal('0') or BigDecimal('-Infinity').

  • true: Raises FloatDomainError.

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): Returns BigDecimal('Infinity') or BigDecimal('-Infinity').

  • true: Raises FloatDomainError.

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): Returns BigDecimal('Infinity') or BigDecimal('-Infinity').

  • true: Raises FloatDomainError.

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 :down and :truncate.

  • ROUND_HALF_UP: Round toward the nearest neighbor; if the neighbors are equidistant, round away from zero. Aliased as :half_up and :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_even and :banker.

  • ROUND_CEILING: Round toward positive infinity. Aliased as :ceiling and :ceil.

  • ROUND_FLOOR: Round toward negative infinity. Aliased as :floor:.



1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
# File 'bigdecimal.c', line 1064

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;
}