diff options
Diffstat (limited to 'activesupport/lib/active_support/number_helper/rounding_helper.rb')
-rw-r--r-- | activesupport/lib/active_support/number_helper/rounding_helper.rb | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/number_helper/rounding_helper.rb b/activesupport/lib/active_support/number_helper/rounding_helper.rb new file mode 100644 index 0000000000..d9644df17d --- /dev/null +++ b/activesupport/lib/active_support/number_helper/rounding_helper.rb @@ -0,0 +1,64 @@ +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 + number = BigDecimal(number.to_s) + when Rational + number = BigDecimal(number, digit_count(number.to_i) + precision) + else + number = 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 |