Module: Numerals::Conversions
- Defined in:
- lib/numerals/conversions.rb
Class Method Summary collapse
- .[](type, options = nil) ⇒ Object
-
.convert(number, options = {}) ⇒ Object
Convert an number to a different numeric type.
- .exact?(number, options = {}) ⇒ Boolean
- .number_of_digits(number, options = {}) ⇒ Object
- .order_of_magnitude(number, options = {}) ⇒ Object
-
.read(numeral, options = {}) ⇒ Object
Convert Numeral to Number.
-
.write(number, options = {}) ⇒ Object
Convert Number to Numeral.
Class Method Details
.[](type, options = nil) ⇒ Object
6 7 8 9 10 |
# File 'lib/numerals/conversions.rb', line 6 def [](type, = nil) if type.respond_to?(:numerals_conversion) type.numerals_conversion( || {}) end end |
.convert(number, options = {}) ⇒ Object
Convert an number to a different numeric type. Conversion is done by first converting the number to a Numeral, then converting the Numeral to de destination type.
Options:
-
:exact_input Consider the number an exact quantity. Otherwise, for approximate types, insignificant digits will not be converted.
-
:rounding Rounding to be applied during the conversion.
-
:type or :context can be used to define the destination type.
-
:output_mode can have the values :free, :short or :fixed and is used to define how the result is generated.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/numerals/conversions.rb', line 128 def convert(number, = {}) if [:exact] = .merge(exact_input: true, ouput_mode: :free) end exact_input = [:exact_input] || false rounding = Rounding[[:rounding] || Rounding[]] output_mode = [:output_mode] || :free # :short :free :fixed = [:type_options] selector = [:context] || [:type] output_conversions = self[selector, ] if output_conversions && output_conversions.respond_to?(:context) output_base = output_conversions.context.radix if rounding.base != output_base && rounding.free? rounding = rounding[base: output_base] end end if number.is_a?(Numeral) numeral = number else = { exact: exact_input, rounding: rounding, type_options: } numeral = write(number, ) end = { type: [:type], context: [:context] } case output_mode when :short .merge!( exact: false, simplify: true ) when :free .merge!( exact: false, simplify: false ) when :fixed .merge!( exact: true, simplify: false ) end if ![:exact] && numeral.exact? numeral.approximate! end read(numeral, ) end |
.exact?(number, options = {}) ⇒ Boolean
109 110 111 |
# File 'lib/numerals/conversions.rb', line 109 def exact?(number, = {}) self[number.class, [:type_options]].exact?(number, ) end |
.number_of_digits(number, options = {}) ⇒ Object
16 17 18 |
# File 'lib/numerals/conversions.rb', line 16 def number_of_digits(number, ={}) self[number.class, [:type_options]].number_of_digits(number, ) end |
.order_of_magnitude(number, options = {}) ⇒ Object
12 13 14 |
# File 'lib/numerals/conversions.rb', line 12 def order_of_magnitude(number, ={}) self[number.class, [:type_options]].order_of_magnitude(number, ) end |
.read(numeral, options = {}) ⇒ Object
Convert Numeral to Number
read numeral, ={}
If the input numeral is approximate and the destination type allows for arbitrary precision, then the destination context precision will be ignored and the precision of the input will be preserved. The :simplify option affects this case by generating only the mininimun number of digits needed.
The :exact option will prevent this behaviour and always treat input as exact.
Valid output options:
-
:type class of the output number
-
:context context (in the case of Flt::Num, Float) for the output
-
:simplify (for approximate input numeral/arbitrary precision type only)
-
:exact treat input numeral as if exact
40 41 42 43 44 45 46 |
# File 'lib/numerals/conversions.rb', line 40 def read(numeral, ={}) selector = [:context] || [:type] exact_input = [:exact] approximate_simplified = [:simplify] conversions = self[selector, [:type_options]] conversions.read(numeral, exact_input, approximate_simplified) end |
.write(number, options = {}) ⇒ Object
Convert Number to Numeral
write number, ={}
Valid options:
-
:rounding (a Rounding) (which defines output base as well)
-
:exact (exact input indicator)
Approximate mode:
If the input is treated as an approximation (which is the case for types such as Flt::Num, Float,… unless the :exact option is true) then no ‘spurious’ digits will be shown (digits that can take any value and the numeral still would convert to the original number if rounded to the same precision)
In approximate mode, if rounding is simplifying? (:short), the shortest representation which rounds back to the origina number with the same precision is used. If rounding is :free and the output base is the same as the number internal radix, the exact precision (trailing zeros) of the number is represented.
Exact mode:
Is used for ‘exact’ types (such as Integer, Rational) or when the :exact option is defined to be true.
The number is treated as an exact value, and converted according to Rounding. (in this case the :free and :short precision roundings are equivalent)
Summary
In result there are 5 basically diferent conversion modes. Three of them apply only to approximate values, so they are not available for all input types:
-
‘Short’ mode, which produces an exact Numeral. Used when input is not exact and rounding precision is :short.
-
‘Free’ mode, which produces an approximate Numeral. Used when input is not exact and rounding precision is :short.
-
‘Fixed’ mode, which produces an approximate Numeral. Used when input isnot exact and rounding precision is limited.
The other two modes are applied to exact input, so they’re available for all input types (since all can be taken as exact with the :exact option):
-
‘All’ mode, which produces an exact Numeral. Used when input is exact and rounding precision is :free (or :short).
-
‘Rounded’ mode, which produces an approximate Numeral. Used when input is exact and rounding precision is limited.
102 103 104 105 106 107 |
# File 'lib/numerals/conversions.rb', line 102 def write(number, = {}) output_rounding = Rounding[[:rounding] || Rounding[]] conversion = self[number.class, [:type_options]] exact_input = conversion.exact?(number, ) conversion.write(number, exact_input, output_rounding) end |