Class: Plurimath::Formatter::Numbers::Source

Inherits:
Object
  • Object
show all
Defined in:
lib/plurimath/formatter/numbers/source.rb

Overview

Captures raw input, BigDecimal interpretation, and source digit metadata before formatter transforms run.

Constant Summary collapse

DEFAULT_INTEGER =
"0"
EMPTY_STRING =
""
NUMERIC_PATTERN =

Stricter than BigDecimal(), which tolerates underscores, surrounding junk after partial parses, and Infinity/NaN spellings.

/\A[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, base: Base::DEFAULT_BASE) ⇒ Source

Returns a new instance of Source.



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/plurimath/formatter/numbers/source.rb', line 20

def initialize(value, base: Base::DEFAULT_BASE)
  @raw = value.to_s
  @base = base || Base::DEFAULT_BASE
  validate_numeric!(value)
  @decimal = parse_decimal
  @sign = raw.start_with?("-") ? -1 : 1

  mantissa, @exponent_text = unsigned_value.split("e", 2)
  @exponent = exponent_text.to_i
  @integer_digits, @fraction_digits = split_mantissa(mantissa)
end

Instance Attribute Details

#decimalObject (readonly)

Returns the value of attribute decimal.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def decimal
  @decimal
end

#exponentObject (readonly)

Returns the value of attribute exponent.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def exponent
  @exponent
end

#exponent_textObject (readonly)

Returns the value of attribute exponent_text.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def exponent_text
  @exponent_text
end

#fraction_digitsObject (readonly)

Returns the value of attribute fraction_digits.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def fraction_digits
  @fraction_digits
end

#integer_digitsObject (readonly)

Returns the value of attribute integer_digits.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def integer_digits
  @integer_digits
end

#rawObject (readonly)

Returns the value of attribute raw.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def raw
  @raw
end

#signObject (readonly)

Returns the value of attribute sign.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def sign
  @sign
end

Instance Method Details

#decimal_precisionObject



36
37
38
# File 'lib/plurimath/formatter/numbers/source.rb', line 36

def decimal_precision
  decimal_digits.last.length
end

#fractional?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/plurimath/formatter/numbers/source.rb', line 32

def fractional?
  fraction_digits.length > exponent
end

#notation_precisionObject



40
41
42
43
44
45
46
47
48
# File 'lib/plurimath/formatter/numbers/source.rb', line 40

def notation_precision
  # A zero coefficient keeps the source's stated fraction width.
  return fraction_digits.length if decimal.zero?

  # The coefficient's fraction width is its significant-digit count
  # minus the single leading digit; the sign and leading zeros carry
  # no precision.
  [significant_digit_count - 1, 0].max
end

#significant_digit_countObject



50
51
52
# File 'lib/plurimath/formatter/numbers/source.rb', line 50

def significant_digit_count
  significant_digits.length
end

#target_base_integer_length(base) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/plurimath/formatter/numbers/source.rb', line 54

def target_base_integer_length(base)
  return decimal_parts_integer_length if base == Base::DEFAULT_BASE

  integer = decimal.abs.to_i
  return 0 if integer.zero?

  integer.to_s(base).length
end

#to_parts(base: nil, precision: nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/plurimath/formatter/numbers/source.rb', line 63

def to_parts(base: nil, precision: nil)
  integer, fraction = decimal_digits
  fraction = apply_precision(fraction, precision)

  Parts.new(
    sign: sign,
    base: base || Base::DEFAULT_BASE,
    integer_digits: integer,
    fraction_digits: fraction,
  )
end

#trailing_fraction_zero_countObject



75
76
77
78
79
# File 'lib/plurimath/formatter/numbers/source.rb', line 75

def trailing_fraction_zero_count
  return 0 if fraction_digits.empty?

  fraction_digits.length - fraction_digits.sub(/0+\z/, "").length
end