blob: a5b28296a27376753a9f73053143e93109ebbd34 (
plain) (
tree)
|
|
# frozen_string_literal: true
module ActiveSupport
module NumberHelper
class RoundingHelper # :nodoc:
attr_reader :options
def initialize(options)
@options = options
end
def round(number)
return number unless precision
number = convert_to_decimal(number)
if significant && precision > 0
round_significant(number)
else
round_without_significant(number)
end
end
def digit_count(number)
return 1 if number.zero?
(Math.log10(absolute_number(number)) + 1).floor
end
private
def round_without_significant(number)
number = number.round(precision)
number = number.to_i if precision == 0 && number.finite?
number = number.abs if number.zero? # prevent showing negative zeros
number
end
def round_significant(number)
return 0 if number.zero?
digits = digit_count(number)
multiplier = 10**(digits - precision)
(number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
end
def convert_to_decimal(number)
case number
when Float, String
BigDecimal(number.to_s)
when Rational
BigDecimal(number, digit_count(number.to_i) + precision)
else
number.to_d
end
end
def precision
options[:precision]
end
def significant
options[:significant]
end
def absolute_number(number)
number.respond_to?(:abs) ? number.abs : number.to_d.abs
end
end
end
end
|