Class: Numerals::BigDecimalConversion

Inherits:
ContextConversion show all
Defined in:
lib/numerals/conversions/bigdecimal.rb

Instance Attribute Summary

Attributes inherited from ContextConversion

#context, #input_rounding, #type

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ BigDecimalConversion

Options:

  • :input_rounding (optional, a non-exact Rounding or rounding mode) which is used when input is approximate as the assumed rounding mode which would be used so that the result numeral rounds back to the input number



14
15
16
# File 'lib/numerals/conversions/bigdecimal.rb', line 14

def initialize(options = {})
  super BigDecimal, options
end

Instance Method Details

#exact?(value, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/numerals/conversions/bigdecimal.rb', line 39

def exact?(value, options={})
  options[:exact]
end

#number_of_digits(value, options = {}) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/numerals/conversions/bigdecimal.rb', line 27

def number_of_digits(value, options={})
  base = options[:base] || 10
  precision = x.precs.first
  decimal_digits = x.split[1].size
  n = decimal_digits # or use precision?
  if base == 10
    n
  else
    Flt::DecNum.context[precision: n].necessary_digits(base)
  end
end

#number_to_numeral(number, mode, rounding) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/numerals/conversions/bigdecimal.rb', line 43

def number_to_numeral(number, mode, rounding)
  if @context.special?(number)
    special_num_to_numeral number
  else
    if mode == :exact
      exact_num_to_numeral number, rounding
    else # mode == :approximate
      approximate_num_to_numeral(number, rounding)
    end
  end
end

#numeral_to_number(numeral, mode) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/numerals/conversions/bigdecimal.rb', line 55

def numeral_to_number(numeral, mode)
  if numeral.special?
    special_numeral_to_num numeral
  elsif mode == :fixed
    fixed_numeral_to_num numeral
  else # mode == :free
    free_numeral_to_num numeral
  end
end

#order_of_magnitude(value, options = {}) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/numerals/conversions/bigdecimal.rb', line 18

def order_of_magnitude(value, options={})
  base = options[:base] || 10
  if base == 10
    value.exponent
  else
    (Math.log(value.abs)/Math.log(base)).floor + 1
  end
end

#read(numeral, exact_input, approximate_simplified) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/numerals/conversions/bigdecimal.rb', line 100

def read(numeral, exact_input, approximate_simplified)
  if numeral.special?
    special_numeral_to_num numeral
  elsif numeral.approximate? && !exact_input
    if approximate_simplified
      # akin to @context.Num(numeral_text, :short)
      short_numeral_to_num numeral
    else
      # akin to @context.Num(numeral_text, :free)
      free_numeral_to_num numeral
    end
  else
    # akin to @context.Num(numeral_text, :fixed)
    fixed_numeral_to_num numeral
  end
end

#write(number, exact_input, output_rounding) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/numerals/conversions/bigdecimal.rb', line 65

def write(number, exact_input, output_rounding)
  output_base = output_rounding.base
  input_base = @context.radix

  if @context.special?(number)
    special_num_to_numeral number
  elsif exact_input
    if output_base == input_base && output_rounding.free?
      # akin to number.format(base: output_base, simplified: true)
      if true
        # ALT.1 just like approximate :short
        general_num_to_numeral number, output_rounding, false
      else
        # ALT.2 just like different bases
        exact_num_to_numeral number, output_rounding
      end
    else
      # akin to number.format(base: output_base, exact: true)
      exact_num_to_numeral number, output_rounding
    end
  else
    if output_base == input_base && output_rounding.preserving?
      # akin to number.format(base: output_base)
      sign, coefficient, exponent = @context.split(number)
      Numerals::Numeral.from_coefficient_scale sign*coefficient, exponent, approximate: true
    elsif output_rounding.simplifying?
      # akin to number.forma(base: output_base, simplify: true)
      general_num_to_numeral number, output_rounding, false
    else
      # akin to number.forma(base: output_base, all_digits: true)
      general_num_to_numeral number, output_rounding, true
    end
  end
end