Sha256: a62eae4e9160e10af204d266adcb7da1f45946f4c1fd2647b7210020c4acaf53

Contents?: true

Size: 1.96 KB

Versions: 3

Compression:

Stored size: 1.96 KB

Contents

# frozen_string_literal: true

module Plurimath
  module Formatter
    class NumberFormatter
      attr_reader :number, :data_reader

      STRING_SYMBOLS = {
        dot: ".".freeze,
        f: "F".freeze,
      }.freeze

      def initialize(number, data_reader = {})
        @number = number
        @data_reader = data_reader
      end

      def format(precision: nil)
        data_reader[:precision] = precision || precision_from(number)
        int, frac, integer_format, fraction_format, signif_format = *partition_tokens(number)
        result = integer_format.apply(int, data_reader)
        result << fraction_format.apply(frac, data_reader, int) if frac

        result = signif_format.apply(result, integer_format, fraction_format)

        result
      end

      private

      def partition_tokens(number)
        int, fraction = parse_number(number, data_reader)
        [
          int,
          fraction,
          Numbers::Integer.new(data_reader),
          Numbers::Fraction.new(data_reader),
          Numbers::Significant.new(data_reader),
        ]
      end

      def precision_from(number)
        return 0 if number.fix == number

        parts = number.to_s(STRING_SYMBOLS[:f]).split(STRING_SYMBOLS[:dot])
        parts.size == 2 ? parts[1].size : 0
      end

      def parse_number(number, options = {})
        precision = options[:precision] || precision_from(number)

        num = if precision == 0
                round_to(number, precision).abs.fix.to_s(STRING_SYMBOLS[:f])
              else
                round_to(number, precision).abs.round(precision).to_s(STRING_SYMBOLS[:f])
              end
        num.split(STRING_SYMBOLS[:dot])
      end

      def round_to(number, precision)
        factor = 10 ** precision
        result = if number.is_a?(BigDecimal)
                   ((number * factor).fix / factor)
                 else
                   ((number * factor).round.to_f / factor)
                 end
        result
      end
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
plurimath-0.8.16 lib/plurimath/formatter/number_formatter.rb
plurimath-0.8.15 lib/plurimath/formatter/number_formatter.rb
plurimath-0.8.14 lib/plurimath/formatter/number_formatter.rb