Class: Numerals::Rounding
- Inherits:
-
FormattingAspect
- Object
- FormattingAspect
- Numerals::Rounding
- Includes:
- ModalSupport::StateEquivalent
- Defined in:
- lib/numerals/rounding.rb
Overview
Rounding of Numerals
Constant Summary collapse
- DEFAULTS =
{ mode: :half_even, precision: :short, places: nil, base: 10 }
Instance Attribute Summary collapse
-
#base ⇒ Object
Returns the value of attribute base.
-
#mode ⇒ Object
Returns the value of attribute mode.
Instance Method Summary collapse
-
#absolute? ⇒ Boolean
Returns true if the Rounding is of fixed precision defined as a number of fractional places, i.e.
-
#fixed? ⇒ Boolean
Returns true if the Rounding is of fixed (limited) precision.
-
#free? ⇒ Boolean
Returns true if the Rounding is of free (unlimited) precision, which can be either :free (preserving) or :short (simplifying) regarding approximate input.
- #full? ⇒ Boolean
-
#initialize(*args) ⇒ Rounding
constructor
Rounding defines a rounding mode and a precision, and is used to establish the desired accuracy of a Numeral result.
- #inspect ⇒ Object
- #parameters ⇒ Object
-
#places(value = nil, options = {}) ⇒ Object
Number of fractional places for a given numerical/numeral value If no value is passed, the :places property is returned.
- #places=(v) ⇒ Object
-
#precision(value = nil, options = {}) ⇒ Object
Number of significant digits for a given numerical/numeral value.
- #precision=(v) ⇒ Object
-
#preserving? ⇒ Boolean
Returns true if the Rounding is of free precision and the behaviour for approximate numbers is to keep its original precision (so it may include trailing zeros) and the result of rounding will be an approximate numeral.
-
#relative? ⇒ Boolean
Returns true if the Rounding is of fixed precision defined as a number of significant digits (precision attribute), i.e.
-
#round(numeral, options = {}) ⇒ Object
Round a numeral.
- #short? ⇒ Boolean
-
#simplifying? ⇒ Boolean
Returns true if the Rounding is of free precision and the behaviour for approximate numbers is producing a simplified (short) result with only the needed digits to restore the original value within its precision.
- #to_s ⇒ Object
Methods inherited from FormattingAspect
Constructor Details
#initialize(*args) ⇒ Rounding
Rounding defines a rounding mode and a precision, and is used to establish the desired accuracy of a Numeral result.
Rounding also defines the base of the numerals to be rounded, which is 10 by default.
The rounding mode is the rule used to limit the precision of a numeral; the rounding modes available are those of Flt::Num, namely:
-
:half_even
-
:half_up
-
:half_down
-
:ceiling
-
:floor
-
:up
-
:down
-
:up05
Regarding the rounding precision there are two types of Roundings:
-
Fixed (limited) precision: the precision of the rounded result is either defined as relative (number of significant digits defined by the precision property) or absolute (number of fractional places –decimals for base 10– defined by the places property)
-
Free (unlimited) precision, which preserves the value of the input numeral. As much precision as needed is used to keep unambiguously the original value. When applied to exact input, this kind of rounding doesn’t perform any rounding. For approximate input there are two variants:
-
Preserving the original value precision, which produces and approximate output. (All original digits are preserved; full precision mode). This is the default free precision mode, established by using the :free symbol for the precision (or its synonym :preserve).
-
Simplifiying or reducing the result to produce an exact output without unneeded digits to restore the original value within its original precision (e.g. traling zeros are not keep). This case can be defined with the :short symbol for the precision (or its synonum :simplify).
-
47 48 49 50 51 52 |
# File 'lib/numerals/rounding.rb', line 47 def initialize(*args) DEFAULTS.each do |param, value| instance_variable_set "@#{param}", value end set! *args end |
Instance Attribute Details
#base ⇒ Object
Returns the value of attribute base.
61 62 63 |
# File 'lib/numerals/rounding.rb', line 61 def base @base end |
#mode ⇒ Object
Returns the value of attribute mode.
61 62 63 |
# File 'lib/numerals/rounding.rb', line 61 def mode @mode end |
Instance Method Details
#absolute? ⇒ Boolean
Returns true if the Rounding is of fixed precision defined as a number of fractional places, i.e. independently of the number to be rounded’s magnitude.
126 127 128 |
# File 'lib/numerals/rounding.rb', line 126 def absolute? @precision.nil? # fixed? && @precision # [email protected]? end |
#fixed? ⇒ Boolean
Returns true if the Rounding is of fixed (limited) precision.
119 120 121 |
# File 'lib/numerals/rounding.rb', line 119 def fixed? # limited? approximate? rounding? fixed? !free? end |
#free? ⇒ Boolean
Returns true if the Rounding is of free (unlimited) precision, which can be either :free (preserving) or :short (simplifying) regarding approximate input.
114 115 116 |
# File 'lib/numerals/rounding.rb', line 114 def free? # unlimited? exact? all? nonrounding? free? [:free, :short].include?(@precision) end |
#full? ⇒ Boolean
157 158 159 |
# File 'lib/numerals/rounding.rb', line 157 def full? preserving? end |
#inspect ⇒ Object
107 108 109 |
# File 'lib/numerals/rounding.rb', line 107 def inspect to_s end |
#parameters ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/numerals/rounding.rb', line 91 def parameters if @precision { mode: @mode, precision: @precision, base: @base } else { mode: @mode, places: @places, base: @base } end end |
#places(value = nil, options = {}) ⇒ Object
Number of fractional places for a given numerical/numeral value If no value is passed, the :places property is returned.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/numerals/rounding.rb', line 183 def places(value = nil, = {}) if value.nil? @places elsif is_exact?(value, ) @places || 0 elsif free? num_digits(value, ) - num_integral_digits(value) else # fixed? if absolute? @places else # relative? @precision - num_integral_digits(value) end end end |
#places=(v) ⇒ Object
86 87 88 89 |
# File 'lib/numerals/rounding.rb', line 86 def places=(v) @places = v @precision = nil if @places end |
#precision(value = nil, options = {}) ⇒ Object
Number of significant digits for a given numerical/numeral value. If no value is passed, the :precision property is returned.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/numerals/rounding.rb', line 163 def precision(value = nil, = {}) if value.nil? @precision elsif free? if is_exact?(value, ) 0 else num_digits(value, ) end else # fixed? if absolute? @places + num_integral_digits(value) else # relative? @precision end end end |
#precision=(v) ⇒ Object
80 81 82 83 84 |
# File 'lib/numerals/rounding.rb', line 80 def precision=(v) @precision = v @precision = :simplify if v == 0 @places = nil if @precision end |
#preserving? ⇒ Boolean
Returns true if the Rounding is of free precision and the behaviour for approximate numbers is to keep its original precision (so it may include trailing zeros) and the result of rounding will be an approximate numeral.
153 154 155 |
# File 'lib/numerals/rounding.rb', line 153 def preserving? @precision == :free end |
#relative? ⇒ Boolean
Returns true if the Rounding is of fixed precision defined as a number of significant digits (precision attribute), i.e. in relation to the number to be rounded’s magnitude.
133 134 135 |
# File 'lib/numerals/rounding.rb', line 133 def relative? fixed? && !absolute? end |
#round(numeral, options = {}) ⇒ Object
Round a numeral. If the numeral has been truncated the :round_up option must be used to pass the information about the discarded digits:
-
nil if all discarded digits where 0 (the truncated value is exact)
-
:lo if there where non-zero discarded digits, but the first discarded digit is below half the base.
-
:tie if the first discarded was half the base and there where no more nonzero digits, i.e. the original value was a ‘tie’, exactly halfway between the truncated value and the next value with the same number of digits.
-
:hi if the original value was above the tie value.
209 210 211 212 213 214 215 216 217 |
# File 'lib/numerals/rounding.rb', line 209 def round(numeral, ={}) round_up = [:round_up] numeral, round_up = truncate(numeral, round_up) if numeral.exact? numeral else adjust(numeral, round_up) end end |
#short? ⇒ Boolean
145 146 147 |
# File 'lib/numerals/rounding.rb', line 145 def short? end |
#simplifying? ⇒ Boolean
Returns true if the Rounding is of free precision and the behaviour for approximate numbers is producing a simplified (short) result with only the needed digits to restore the original value within its precision.
141 142 143 |
# File 'lib/numerals/rounding.rb', line 141 def @precision == :short end |
#to_s ⇒ Object
99 100 101 102 103 104 105 |
# File 'lib/numerals/rounding.rb', line 99 def to_s params = parameters DEFAULTS.each do |param, default| params.delete param if params[param] == default end "Rounding[#{params.inspect.unwrap('{}')}]" end |